5

I am a developer on an open source project and I have been having some problems with the server thinking it has answered a socket completely (meaning it has either sent a reply or closed it's end in response to a failure) and the client being stuck in poll(). After some research, I found that close() doesn't always generate a POLLHUP event, but shutdown(sock, 2) does.

In light of that, I'm considering adding a shutdown(sock,2) in the event of error handling (in addition to the close() call). Does anyone know of some reasons that this would cause problems? Am I barking up the wrong tree? I'm thinking that if the server believes that the socket is closed, the client should definitely not attempt anything else with that socket, and I can't think of a reason not to add this, but I haven't been working with tcp connections for that long and would love some advice.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
dbeer
  • 6,963
  • 3
  • 31
  • 47
  • I would recommend this read: http://stackoverflow.com/questions/409783/socket-shutdown-vs-socket-close – brain Sep 14 '11 at 22:37
  • brain, that is an interesting read but it doesn't give me any reasons I wouldn't want to call shutdown in conjunction with close. – dbeer Sep 14 '11 at 22:54

2 Answers2

3

You need to figure out why closeing the socket isn't causing it to shutdown. The most likely reason is that there is another descriptor that accesses the same endpoint. Only closeing the last endpoint causes an implicit shutdown.

Do you ever dup the file descriptor? Do you make sure it is closed in all child processes? If the socket was in a parent process before it forked this process, did the parent close their copy?

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • David, thanks for the advice. I have a feeling that the problem lies in tracking down what you said. I believe I have removed all forks from the code in favor of threads, but I will check into dups. One question though - does a close() always cause a shutdown when it is closed properly? – dbeer Sep 15 '11 at 16:57
  • A close causes an implicit shutdown if closes the last descriptor that references that endpoint. The behavior of an implicit shutdown depends on the 'linger on close' settings. – David Schwartz Sep 15 '11 at 20:10
  • `close` does not return error information. It therefore is almost never a substitute for `shutdown`. You don't know whether what you sent has been received. – usr Feb 08 '14 at 22:30
0

POLLHUP is not the right way to test for a closed connection. You should be testing for the file descriptor becoming readable and subsequently returning a zero-length read. This is the definition of end-of-file.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • R, the code is using poll() with the set: pollset.events = POLLIN | POLLHUP; For reasons beyond my control, I can't change it from the poll() model. Either way, the client is blocking on that poll until timeout happens. – dbeer Sep 14 '11 at 22:47
  • 1
    Yes, then check for `POLLIN`. EOF is a zero-length read that shows up as input available for read. – R.. GitHub STOP HELPING ICE Sep 14 '11 at 22:47
  • 1
    -1 `POLLHUP` IS the right way to check on some systems (MacOS comes to mind); the POSIX spec allows either. So you really need to check for `POLLHUP|POLLIN` if you want to be portable. – Chris Dodd Sep 15 '11 at 00:19
  • @Chris: Citation? Even if you were right, I'm pretty sure this answer solves the problem OP encountered. – R.. GitHub STOP HELPING ICE Sep 15 '11 at 01:59
  • The code does check for POLLIN and POLLHUP (sorry I accidentally posted and then had to edit) but my problem persists. – dbeer Sep 15 '11 at 16:53
  • It has happened on multiple versions of ubuntu. – dbeer Sep 15 '11 at 19:42
  • I think you need to elaborate on the operations the client and server are performing. Showing either some code or `strace` of the last few syscalls leading up the the client hanging and not realizing the server closed the connection would probably be sufficient. – R.. GitHub STOP HELPING ICE Sep 15 '11 at 20:25