8

I'm currently writing a small server application, and my problem is, that when I close my app (or better, press the terminate button in eclipse), the socket sometimes stays open, so when I execute my app the next time, bind() will fail with "Address already in use". How can I properly close my sockets when the program exits? I already put

close(mySocket);

in the class destructors, but that doesn't seem to change anything.

fresskoma
  • 25,481
  • 10
  • 85
  • 128
  • Are you sure the destructors are running? Can you put some output or a breakpoint there to see? – David Thornley Aug 06 '09 at 20:35
  • TCP is standardized "on the wire" but not at the API level. Therefore, one of the most important things when asking questions regarding TCP is to disclose the platform. – Chris Cleeland Aug 06 '09 at 20:57

6 Answers6

7

Use SO_REUSEADDR.

Community
  • 1
  • 1
bdonlan
  • 224,562
  • 31
  • 268
  • 324
4

http://hea-www.harvard.edu/~fine/Tech/addrinuse.html should answer a lot of your questions. I tend to use SO_REUSEADDR to work around that problem.

Tynan
  • 171
  • 1
  • 5
  • Ok, if I get it right, this kind of ignores that the socket is still reported as in-use. But is there any way to properly close it in the first place? – fresskoma Aug 06 '09 at 20:30
  • Yes, but where. Where whould I have to call it to get it executed when my app gets terminated. – fresskoma Aug 06 '09 at 20:38
  • 5
    Calling close() won't necessarily avoid address already in use. If the kernel doesn't get the ACK back from the FIN you sent by calling close before the process ends, the bound socket will go into TIME_WAIT, and you'll have to wait a few minutes before the kernel decides that it probably won't get reused. Setting SO_REUSEADDR will allow the kernel to immediately reuse that address instead. – Tynan Aug 06 '09 at 20:47
  • `TIME_WAIT` has nothing to do with whether the far side sends an ACK. See the state transition diagram at http://userpages.umbc.edu/~jeehye/cmsc491b/lectures/tcpstate/sld001.htm and the explanation of the TIME_WAIT state in my answer below. – Chris Cleeland Aug 06 '09 at 22:52
  • To answer where you would have to call it. You need to catch the SIGTERM signal (the signal sent to TERMinate a process before resorting to a SIGKILL), and perhaps the SIGINT signal, and call close() in the handler for that signal. – David Claridge Aug 07 '09 at 04:20
4

Use netstat to figure out what state your endpoint is in. My guess is that it's in either TIME_WAIT and not fully closed. This is correct behavior for TCP, and exists to allow stray segments that might still be out in the ether to arrive and not cause problems. The duration of TIME_WAIT is something like 2*MSL, i.e. twice the maximum lifetime of a segment on the network, thus insuring that even a segment that gets retransmitted gets properly handled.

As others have pointed out, SO_REUSEADDR is your friend as long as the far side's endpoint is different each time. That's the common case, but sometimes people do weird things like bind a client to a specific port, and in that case you'll still end up with an EADDRINUSE b/c TCP defines a session as both endpoints.

Chris Cleeland
  • 4,760
  • 3
  • 26
  • 28
2

Have you set the SO_REUSEADDR option? From what you're saying, it seems not.

Geo
  • 93,257
  • 117
  • 344
  • 520
0

Don't forget to check the return value of close. It will return 0 when the socket is successfully closed. It will return -1 if it failed.

-1

Are you sure your app is not somehow still running in the background?

Juan
  • 3,667
  • 3
  • 28
  • 32
  • Yep, pretty much. kill -9 should definitely shut it down, shouldn't it? Anyway, can't find it when I grep over ps -A. – fresskoma Aug 06 '09 at 20:26
  • Kill -9 should take care of it. That is surprising. – Juan Aug 06 '09 at 20:29
  • Except that kill -9 means "SHUT THIS THING DOWN NOW", not "tell this thing to shut itself down properly". It won't call destructors. – David Thornley Aug 06 '09 at 20:33
  • 1
    Perhaps you can write a signal handler to terminate all of your open connections if a ctrl-c or some other condition happens. – Juan Aug 06 '09 at 20:35
  • 1
    kill -9 won't call dtors, but on [most] unix, process shutdown closes open file descriptors, which closes sockets. – Chris Cleeland Aug 06 '09 at 20:58