11

I'm writing a very simple server that loops forever until Ctrl-C is pressed. I'd like to have the signal handler for ctrl-c close the open sockets and shut down the server, but I don't know what the scope is for a signal handler, and I don't like the idea of declaring the socket(s) I would need to close to be global.

Can someone offer suggestions? Is there some standard way to do this?

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
Zxaos
  • 7,791
  • 12
  • 47
  • 61

2 Answers2

11

Well, since you have signal handlers, I'm going to assume you're on a Unix variant. If so:

  • A socket is identified to the kernel by the file number, which is an int. See socket(2).
  • That int is valid for your process
  • That int is valid for any processes forked after creating it
  • If not close-on-exec, it is valid for any process you exec.

So, it's perfectly valid in your signal handler. How you make your signal handler aware of which number to use depends on the language you're writing in, which you didn't specify. There are two approaches that will work in pretty much any language

  • If you don't have any cleanup to do except close and exit, just call exit. Or set the signal action to default, which is exit. The kernel will close the sockets.
  • Set a flag (which will generally be a global of some sort) to tell your select/poll loop to clean up and exit. Advantageous in that you don't have to worry about if various parts of your program are safe to call from a signal handler.
derobert
  • 49,731
  • 15
  • 94
  • 124
  • Isnt the operating system responsible for the clean up after close being called ? – Bionix1441 Dec 02 '16 at 16:37
  • 1
    @Bionix1441 I guess that's a question about the second bullet point "clean up and exit"? I mean, your program may have *other* cleanup to do (e.g., save modified data, delete lockfiles,...). That's a lot easier to do outside of a signal handler. – derobert Dec 02 '16 at 16:40
  • If you want to terminate the 'accept' call upon SIGINT, you have to disable the SA_RESTART flag on the signal handler (see https://stackoverflow.com/questions/15617562/sigintctrlc-doesnt-interrupt-accept-call). – Cl00e9ment Apr 08 '22 at 07:42
10

Normally, it's advisable not to do anything much in a signal handler; other than set a flag.

Then when control returns to your main loop you can examine this flag, exit the loop, close sockets, run destructors on your objects etc, and exit cleanly.

Signal handlers can get called at almost any time, including in the middle of C or C++ library calls, which could be a problem.

Josh
  • 44,706
  • 7
  • 102
  • 124
MarkR
  • 62,604
  • 14
  • 116
  • 151