NetBSD-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: ECONNRESET not returned when calling send() on a socket



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


Home | Main Index | Thread Index | Old Index