libevent with non blocking sockets: If the remote peer sends RST *while* send on local is executed, will local get EV_READ also

StackOverflow https://stackoverflow.com/questions/17364629

  •  01-06-2022
  •  | 
  •  

Question

From the libevent documentation, I understand that when a TCP segment is received from the remote peer, an EV_READ event is generated. What happens in the following scenario

  1. Non blocking application having registered for both read and write events on the socket
  2. Scenario A : Application is waiting for an event. It gets a FIN from remote, EV_READ event is generated, application does a read(or recv) and gets 0
  3. Scenario B: Application is sending data. It gets a FIN from remote while the send is being executed. Will the application get an EPIPE (I think so). Will there also be an EV_READ event generated for the same FIN for which the application gets an EPIP

A related question is that if send and write are similar as mentioned in this, then why is ECONNRESET not generated in write as in the manual page here but generated in send as described in the manual page here.

How do I write a remote peer so that the local send returns an ECONNRESET. Thanks for any answers

Was it helpful?

Solution

Scenario A : Application is waiting for an event. It gets a FIN from remote, EV_READ event is >generated, application does a read(or recv) and gets 0

Yes - that's right.

Scenario B: Application is sending data. It gets a FIN from remote while the send is being >executed. Will the application get an EPIPE (I think so). Will there also be an EV_READ event >generated for the same FIN for which the application gets an EPIPE

Yes, there will be an EV_READ event generated. (ofcourse provided you didn't close() the socket in the mean time).

However you're not getting an error on write in this very particular case. When you get a FIN from the peer end, the TCP connection is only half closed. The incoming FIN simply means "I've nothing more to send". But you can send it more data. Or you can close() the socket, resulting in a FIN from your side to the peer, and now the TCP connection is considered closed, as you've both sent FIN packets.

At this point it depends on what the peer actually did, whether it called close() or shutdown(). On subsequent write()'s you might get EPIPE or ECONNRESET if the peer application closed its socket and the peer sent a RST, or you might continue sending it data if the peer has been coded to receive more data.

note that you're just describing one particular case. Depending on timing and what's happening on the network or at the peer, there's many, many more cases to consider.

How do I write a remote peer so that the local send returns an ECONNRESET.

This will happen if the peer does a close() while there is still data to be read in the local buffers at the peer. In that case a RST is sent, write/send would error with ECONNRESET, as would a read()/recv().

To generate this case, simply don't read() anything, wait a bit until you're sure some data has arrived, then close() the socket. A later write() on the other end would get ECONNRESET. And another write() after ECONNRESET should get EPIPE.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top