tags:

views:

443

answers:

6

Hey folks,
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.
Thank you.

A: 

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

Juan
Yep, pretty much. kill -9 should definitely shut it down, shouldn't it? Anyway, can't find it when I grep over ps -A.
x3ro
Kill -9 should take care of it. That is surprising.
Juan
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
Perhaps you can write a signal handler to terminate all of your open connections if a ctrl-c or some other condition happens.
Juan
I'll try that, thanks Juan.
x3ro
kill -9 won't call dtors, but on [most] unix, process shutdown closes open file descriptors, which closes sockets.
Chris Cleeland
+4  A: 

Use SO_REUSEADDR.

bdonlan
+1  A: 

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

Geo
+1  A: 

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
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?
x3ro
Yes. Call `close` on it.
Geo
Yes, but where. Where whould I have to call it to get it executed when my app gets terminated.
x3ro
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
`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
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
+1  A: 

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
A: 

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.

Chad Simpkins