2

I wrote a socket server, running on linux, but this is probably not linux specifix.

I use poll() to check the state of the clients. My clients do an active (half-)close after sending the request. The server constantly getting POLLHUP and POLLERR, because of the client's half-close. I also see POLLRDHUP, so I know that's actually half-close and not a connection close/reset. My problem is that I always get these events even though I already know from previous poll that there was a half-close.

How can I disable this so I do not receive theis event anymore? I tried to do additional read() and do a shutdown(fd, SHUT_RD), but it doesn't seem to help. I don't want poll to wake up for an event I already handled.

user207421
  • 305,947
  • 44
  • 307
  • 483
Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
  • I have similar problem as you, I would like not to get POLLHUP / POLLERR in poll() and only get in revents the events that I have selected. Not sure how this would be done – Bionix1441 Aug 01 '17 at 08:47

2 Answers2

3

Stop including the fd in the readfds set once you get the half close. There's nothing left to read except half-closes. From this point the only thing you can be interested in is 'writable' events.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • readfds (and separate sets) are only for `select`, but you are right, I just had a bug and still polled for read.. banging my head against the wall :) – Karoly Horvath Jul 08 '11 at 13:16
  • But what about named pipes, they could always get some data i,e even after close another process could open it and write some more data. – Kamath Mar 24 '23 at 09:56
0

Just ignore POLLHUP in return flags. The existing code, if correct, will then do what you want.

The fact that you will keep getting half-closes from poll() (outlined by EJP's answer) is a feature, not a bug. It lets you treat half-closed exactly like end-of-file; which is exactly what you want, as in, it lets your application read the last bytes in the socket buffer instead of discarding them (which is the correct semantics of TCP half-close).

Once "ordinary" end-of-file is reached, poll() will always select the file descriptor as ready for read. The loop around poll() is then supposed to read() the data until end-of-file is seen, and then close(). Ignoring the POLLHUP condition lets your program do the exact same thing with the same code in half-closed situations, and get at the last bytes in the socket buffer.

Likewise, you should implement control flow without caring about POLLHUP. If (and only if) you need to throttle a file descriptor (i.e. there is currently nowhere to put the read() bytes into), then remove that descriptor from the poll() set, so that the kernel won't bug you with ready-to-read "interrupts" until you tell it to again (unthrottling). The fact that all the data is already in the socket buffer (which is what the POLLHUP bit indicates) again doesn't make a difference.

DomQ
  • 4,184
  • 38
  • 37
  • 1
    Sorry, but EJP has the correct answer. In my case I cannot `close()`; there's a lot of data to send. If I keep the fd in the read set, poll() will return immediately... – Karoly Horvath Sep 10 '13 at 16:13