How to detect a client-closed connection during a write from our LDAP server?

Stefan Metzmacher metze at samba.org
Fri Oct 14 13:45:53 UTC 2022


Hi Tom,

>> It means RCV_SHUTDOWN gets set as well as TCP_CLOSE_WAIT, but
>> sk->sk_err is not changed to indicate an error.
> 
> This is correct, because the TCP connection is in "half-closed" state.
> The peer has closed, but the outgoing stream is still open. The TCP
> protocol has supported this since forever.
> 
> This is not a transitory state. The connection can remain in it forever.
> The peer is now in FIN_WAIT_2 and will send no further data. It's
> waiting for our FIN, and in turn the local socket is waiting for a
> close() call to do so. But pretty much any other socket operation
> can still be performed.

Thanks for the explanation!

>> It means if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) doesn't
>> hit as we only have RCV_SHUTDOWN and sk_stream_wait_memory returns -EAGAIN.
> 
> Probably because the peer has stopped reading the socket. FIN_WAIT_2 is
> a super-problematic state, because the only way to exit it is to receive
> a FIN or RST, which we're evidently not sending. Most implementations
> run a timer as failsafe, but it's always rather long (minutes).

Yes, we need 'socket options' with TCP_KEEPCNT, TCP_KEEPIDLE, TCP_KEEPINTVL and/or TCP_USER_TIMEOUT
and/or a user space timer in order to have lower timeouts.

>> And tcp_poll has this:
>>
>>          if (sk->sk_shutdown & RCV_SHUTDOWN)
>>                  mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
>>
>> So we'll get EPOLLIN | EPOLLRDNORM | EPOLLRDHUP triggering TEVENT_FD_READ
>> and writev/sendmsg keep getting EAGAIN.
>>
>> metze
> 
> I think the code needs to detect the half-close and give up. It's not
> going to happen promptly any other way.
> 
> I may have missed some other message - is a fix proposed?

It was in the next message:
https://gitlab.com/samba-team/samba/-/merge_requests/2749

metze




More information about the samba-technical mailing list