4

I've got a couple signal handlers I'm using to exit my program cleanly, and I'd like to play nicely with whatever else has hooked them by chaining the signal handlers calls. I'm using sigaction per the man page for signal saying it's not preferred anymore.

Looking at the sigaction struct, there's signal masks and such that are specified, along with several flags. What's the "right" way to call the currently installed handler so that all those options are taken into account?

CharlesB
  • 86,532
  • 28
  • 194
  • 218
gct
  • 14,100
  • 15
  • 68
  • 107

2 Answers2

4

The answer is "it depends": on what the signal handlers do:

  • The first reaction from many will be that a signal handler will be used to handle a SIGINT, etc., and terminate a program cleanly.
  • On the other hand, there are (more or less) benign signals such as SIGWINCH (which you would like to not stop your program).

In "terminate a program cleanly", there may not be room for other programs to do something useful. For instance, the proposed chained-handler may close files that you rely upon. So you have to start with a good knowledge of what the other handlers do.

If the signal handler is in the latter class, simply updating a variable which the application can test, then the signal handler function is just another function. When you call signal to associate a signal with a function, that returns the previous handler (which may be one of the magic values, e.g.,. SIG_DFL, SIG_IGN). If you save that, it's possible to check if it is none of those, and (presumably) a genuine function. Calling that function would continue execution as if it were part of your current signal handler.

It is not a new idea (I used it in the late 1990s), and is discussed occasionally:

And of course:

Community
  • 1
  • 1
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
1

Well, the proper answer IMO is "Don't do that". I think you should reconsider if you plan to chain signal handlers.

Basically, if you have something so critical it has to be cleaned up even if a fatal signal arrives, then you should do that part quickly and reset the signal handlers before letting any other code run.

Signals such as SIGTERM and SIGQUIT should be handled by events that terminate your program in the normal fashion. Typically your signal handler writes on a pipe to message the normal event loop in the application, or sets a global variable if you don't have an event loop.

Perhaps you know this, but please also make sure to read the list of functions that are safe to call from a signal handler. It should be in the man page. Anything except for that list is not safe.

Per Johansson
  • 6,697
  • 27
  • 34
  • Not doing it is ideal, but eg: for SIGINT I have to shutdown cleanly to eg: wait for child processes to quit and wait() on them so they don't get orphaned. If I use SIGCHLD to wait for my own processes to shut down and I'm using Qt (for example), not calling it's SIGCHLD handler will break QProcess, so there's definitely reasons to do it, but no apparently "good" way to do it robustly. – gct Mar 16 '16 at 20:01
  • SIGINT definitely falls into the "signal main event loop" category of signals. You shouldn't do any processing in its handler. – Per Johansson Mar 17 '16 at 08:07
  • 1
    For SIGCHLD it's more complicated I suppose. I'm not a fan of that signal, and usually try to process children without depending on it (e.g. a EOF on a file descriptor can also signal a child exit). – Per Johansson Mar 17 '16 at 08:10