Page MenuHomeFreeBSD

tcp: use a TCP flag to check if connection has been close(2)d
ClosedPublic

Authored by glebius on Jun 29 2022, 4:46 PM.

Details

Summary

The flag SS_NOFDREF is a private flag of the socket layer. It also
is supposed to be read with SOCK_LOCK(), which we don't own here.
The flag is set in soclose() always after calling pru_close, which
is tcp_usr_close(). Thus checking for t_state > TCPS_CLOSE_WAIT
should be equivalent.

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint OK
Unit
No Unit Test Coverage
Build Status
Buildable 46207
Build 43096: arc lint + arc unit

Event Timeline

I don't think that t_state > TCPS_CLOSE_WAIT is equivalent to the user has called close(). It is equivalent to the user has shutdown its sending side. This means the user can just call shutdown(..., SHUT_WR), shutdown(..., SHUT_RDWR), or close(). In the first two cases the socket is still available via the file descriptor.

Please note that the CLOSE primitive of RFC 793 corresponds in the socket API to the shutdown(..., SHUT_WR) call, not to the close() call. See RFC 793.

You are right. So how can we tell that without SS_NOFDREF? Note that this is the only place where it used outside uipc_socket.c, and in my branch it basically goes away as no longer needed. The difference between tcp_usr_shutdown() path and tcp_usr_close() is that in the soisdisconnected() is called or tcp_drop() in the latter case. Maybe we need just one more tp flag that connection went through close()? What do you think?

As far as I understand, RFC 793 does not make any statements how to handle incoming data segments, if the reading side of the socket has been closed. This can happen, because

  1. the process terminated.
  2. the process called close().
  3. the process called shutdown(..., SHUT_RD) or shutdown(..., SHUT_RDWR).

In my personal opinion, these situations should be handled in the same way. From the perspective of the peer, user data can not be delivered anymore, so sending a RST-segment looks fine to me. This would mean you could just drop the so->so_state & SS_NOFDREF the condition. But I guess this would change the behaviour, I think. Although I would prefer the new one. Any other opinions?
If you want, I can test how we handle data arrival after the reading end has been shutdown and also how we handle the case that user data is buffered when we shutdown the reading end. All these situations result in user data sent by the peer not being delivered to the user...

glebius retitled this revision from tcp: use TCP fsm state to check if connection has been close(2)d to tcp: use a TCP flag to check if connection has been close(2)d.Jun 30 2022, 3:11 PM

Use a new TCP flag instead of state.

This revision is now accepted and ready to land.Jun 30 2022, 3:42 PM