On Fri, 9 Dec 2022, Carl Edquist wrote:
On Fri, 9 Dec 2022, Arsen Arsenović wrote:
Originally i had imagined (or hoped) that this broken-pipe detection
could also be used for sockets (that was how the issue came up for
me), but it seems the semantics for sockets are different than for
pipes.
This might require POLLPRI or POLLRDHUP or such. Can you try with
those to the set of events in pollfd?
Oh interesting! I had assumed these wouldn't help - POLLPRI is for OOB data,
and, I had assumed POLLRDHUP was only for polling the read side of a socket
(thus POLL*RD*HUP), to determine if the remote write end was shutdown. But
you are right, poll() returns with POLLRDHUP in revents as soon as the remote
end is closed. Thanks for the tip!
I assume the reason this works is, even though i have in mind that i am
monitoring the socket as an output, the socket serves as an input also (it's
open for RW). So, if my interpretation is correct, POLLRDHUP is actually
monitoring the local read side of the socket. And so, poll() is actually
detecting the remote write side getting shutdown.
This is not technically the same thing as monitoring the local output side,
but if the remote end of the socket closes entirely (shutting down the remote
read and write ends together), then that tells us about the local output side
as well.
This definitely seems to work for the case i was playing with, though i'm not
sure if it would behave as intended if the remote side only shut down its
read or write end (but not both).
Alright, i got a chance to play around with this more locally with
socketpairs. Unfortunately, i've confirmed that POLLRDHUP is clearly
intended for monitoring the local read end of a socket, not the local
write end. (Thus it is not what we want for monitoring an output.)
In each case below, i started with a socket open for RW on both ends, and
poll()ed the local socket fd with POLLRDHUP. I observed the following:
- shutdown local read -> POLLRDHUP
- shutdown local write -> nothing detected
- shutdown remote read -> nothing detected
- shutdown remote write -> POLLRDHUP
This is exactly the reverse of what we want when monitoring a socket as an
output. Shutting down the local read end should be fine (since we are
using it for output). Shutting down the local write end should be
considered like a broken pipe, since nothing further can be sent.
Shutting down the remote read end should also be considered like a broken
pipe, as with a normal pipe. Shutting down the remote write end should be
fine, since supposedly the local end of the socket is used for output.
Again, the reason POLLRDHUP worked in my case is that the remote end
closed completely (shutting down remote read and write). But for cases
where either end (local or remote) shuts down only read or write, using
POLLRDHUP checks for exactly the wrong thing.
It seems that there ought to be a "POLLWRHUP", but as far as i can tell
that does not exist.
...
My conclusion (as far as i can tell) is that we can't do this iopoll jazz
correctly for sockets.
The up side though is that that makes it ok to explicitly check that the
output is a pipe, and then only worry about pipe semantics. Which makes
the select-based implementation safe, since pipe fds are not open for RW.
Carl