On Sun, Sep 22, 2019 at 11:50:57 +0100, Sad Clouds wrote: > 4. Server goes into a while(1) loop and calls send() until -1 is > returned. When -1 is returned and errno is EAGAIN or EWOULDBLOCK, > server goes back to poll() to wait for read/write events. Otherwise if > errno is something else, server prints error message and cleans up the > socket and goes to listen for new connections. > > Now during Step 4, I kill the client so the client TCP sends RST to the > server. During this time server is busy writing to socket with send() > syscall and for some reason send() does not return -1 with errno set to > ECONNRESET when RST arrives for this socket. What I get instead is > SIGPIPE which terminates the server process.
SIGPIPE is the right thing to do here. The server here is a writer/producer in a pipe-like situation: psend | precv -- and if precv dies then in the unix pipe model you just want psend to be killed without fuss, you don't want every psend, i.e. every program, to handle write errors. Literally every program: wc, echo, date, anything with stdout. Of course since you are writing a networking server you DO want to be notifed about send() errors and SIGPIPE gets in the way. So you can tell the kernel, "hey, I know what I'm doing, I will handle this myself". I don't remember off hand which OS has which of these flags, but there're SOCK_NOSIGPIPE - can be or-ed into the type argument of socket(2) SO_NOSIGPIPE - SOL_SOCKET level socket option MSG_NOSIGNAL - send(2) flag > [...] send() would return -1 with errno set to EPIPE. However I > thought that when RST was generated for a socket, the first write to > the socket should always return -1 with errno set to ECONNRESET. See above. This would be against the way pipes work in unix. The program writing to a socket might happily have no clue its stdout is a socket (inetd). As the saying goes, if you don't know how to interpret a negative result of a scientific experiment, you shouldn't be doing that experiment. If you don't know how to handle the error code, you shouldn't be asking for one to be returned to you. If you DO know, you should ask for it - see the assortment of *_NOSIG* flags available to you (also think about c++, java, etc exceptions vs. e.g. go error checking). I'm not sure (without writing a test or looking at the source) what would send() set errno to, EPIPE or ECONNRESET in that case, but for ~all practical purposes the caller can treat them the same. -uwe
