View Issue Details

IDProjectCategoryView StatusLast Update
0005825GNUnettransport servicepublic2020-12-23 12:57
Reporterschanzen Assigned Toschanzen  
PrioritynormalSeverityminorReproducibilityhave not tried
Status assignedResolutionopen 
Summary0005825: setsockopt SO_NOSIGPIPE can fail after socket accept
DescriptionI had to modify the network.c code a bit to find that setting the sockopt NOSIGPIPE after accept() often fails in trasport.
This happens only in macos.
After investigating it seems like this happens when the remote peer closes the socket before we set the option.

The behaviour is thus correct but spams the logs with the below warnings (more general).
The questions is if we can ignore the error at least for transport? At least accept it and log it as DEBUG?
Usually, the handling of this event (error in sockopt after accept) is to try and reconnect.

Additional InformationAug 10 21:24:30-522872 transport-34891 ERROR Assertion failed at network.c:452.
Aug 10 21:24:30-526849 transport-34891 WARNING `accept' failed at service.c:832 with error: Invalid argument
TagsNo tags attached.

Activities

Christian Grothoff

2020-10-29 11:29

manager   ~0017058

I would disable the warning for the *specific* errno that tells you that the other side already closed the connection -- and then close() the connection on our end and return NULL as well.

Additionally, on platforms where this is possible, we should use accept4() to set the socket options immediately upon accepting, instead of burning additional syscalls later.

schanzen

2020-11-02 09:12

manager   ~0017080

Well, the problem is specifically that the errno in this case is "Invalid argument" (EINVAL), because we are calling it on a socket which was closed by the remote peer. between our accept and setockopt.

Christian Grothoff

2020-11-08 18:09

manager   ~0017111

Eh, based on my understanding that would definitively not result in an EINVAL. Looks to me more like some *other* argument to setsockopt() is invalid on that platform (so the FD is OK, but value/sizeof/IP option) are invalid. For example, we use IPPROTO_TCP, which would be bad for a UNIX/UDP socket. Do we 'accept' on UNIX domain sockets? Then setsockopt() of socket_set_nodelay() would fail with EINVAL because the address family of the socket does not match the setsockopt() call. It must be something like this, I don't believe the half-closed story for a second.

schanzen

2020-11-11 10:49

manager   ~0017119

Unlikely, because the error does not happen _always_, but only when the remote peer closed the connection prematurely. And in that case setting the sockopt is invalid. Hence, EINVAL.
I have been digging around that quite a bit and it seems as if this is not against the spec, but only really happens this way on macos.

Christian Grothoff

2020-12-23 12:57

manager   ~0017229

Well, I guess it can't hurt to add logic to react to a failed setsockopt() with a close(). We know setsockopt() should virtually always succeed, so if it does not,logging + close() seems to be a sensible reaction.

Issue History

Date Modified Username Field Change
2019-08-10 21:41 schanzen New Issue
2020-10-29 11:23 schanzen Assigned To => schanzen
2020-10-29 11:23 schanzen Status new => feedback
2020-10-29 11:23 schanzen Assigned To schanzen => Christian Grothoff
2020-10-29 11:29 Christian Grothoff Note Added: 0017058
2020-10-29 11:29 Christian Grothoff Assigned To Christian Grothoff => schanzen
2020-10-29 11:30 Christian Grothoff Status feedback => assigned
2020-11-02 09:12 schanzen Note Added: 0017080
2020-11-08 18:09 Christian Grothoff Note Added: 0017111
2020-11-11 10:49 schanzen Note Added: 0017119
2020-12-23 12:57 Christian Grothoff Note Added: 0017229