Proposal: new signal-handling API
marlowsd at gmail.com
Mon Jul 21 05:10:14 EDT 2008
John Goerzen wrote:
> Thanks for that. I'm on a train to OSCon right now, so my apologies for
> typos or late replies (my net connection is not terribly stable so I
> can't see the whole thing.)
> Overall I think the goal of being able to add signal handlers without
> disturbing what's there is a good one, and being able to add multiple
> handlers like that is a good plan too.
> I do have a few things I'd like to make sure are addressed, though.
> Maybe they are (again, a bit hard to read from my train)...
> 1) Instead of deprecating the low-level API, I would prefer to have it
> still available -- ideally with the new API implemented in terms of it.
> I can see cases where I really want to make the handler be what I say,
> not anything else. For instance, say some library was catching SIGABRT
> for its own purposes, but in a certain section of code, I really want
> SIGABRT to be handled in a certain way. Using the old API, I could save
> off the old handler, install a new handler that does what I want, and
> restore the old one later (assuming I didn't dump core).
> This is important because, for many signals, the "normal" way to handle
> it might be to do something and then crash. For instance, if you get
> sigabrt, maybe you print out some state, then crash. So if something
> installed a signal handler that crashes, you may be stuck if you don't
> want to crash.
> It could also be important if you really don't want other signals
> handlers doing anything. Say you've got a library that installs a
> handler for SIGINT that flushes out some buffer and prepares things for
> the progam to terminate nicely. But in a certain part of your code, you
> don't want to handle SIGINT at all (or you absolutely want it to be
> handled only by saying putStrLn "Don't press Ctrl-C now, you dolt!").
> Since adding a signal handler could be opaque, this could be quite
> difficult. With the proposed system, you never know if some module has
> installed a signal handler, which could be an issue in itself.
So one reason I wanted to deprecate the old API is that with signals run in
separate threads it didn't really make sene. For example, asking for a
signal to be ignored isn't useful on its own: there might be signal
handlers for that signal already running, or just started and about to run.
Blocking signals suffers from the same problem. (I know I left the
blocking primitives around in the new API, I should really deprecate them
Synchronising with signal handlers should be done using ordinary thread
synchronisation. Have one big signal lock if you like, or one per signal,
or one per handler - it's up to you.
It's true that you can't synchronise with other people's signal handlers
this way. But I think that's a feature, or at least not a bug. Even using
SIG_IGN or sigprocmask() you couldn't stop a handler that had already been
To do what you describe with SIGINT, you would:
- say to the default ^C handler "don't deliver any ^C exceptions until I
tell you otherwise" (GHC 6.9+ has a default ^C handler, and there will
be a way to communicate/synchronise with it or disable it).
- install another handler temporarily to do putStrLn "don't press ^C...".
Random libraries would not be adding ^C handlers to do cleanup. Libraries
that need cleanup should be providing a function
withMyLib :: IO a -> IO a
that does a "finally"-style action to perform the cleanup.
> 2) It would be nice to at least have the option of atomic handlers in
> Haskell. I realize this is not a regression over 6.8.2. Failing that,
> it would be nice to have it documented whether forkIO or forkOS is used.
The idea of atomic signal handlers in the context of GHC scares me :-)
Either the handler would have to avoid touching any kind of shared resource
(e.g. a Handle) to avoid deadlock, or we'd have to block signals whenever
another thread was holding the resource (not really practical). The list
of things you could do in a signal handler would be pretty small - most I/O
would be out.
Also signal handlers are not atomic even in POSIX when there are multiple
threads, right? They're only atomic with respect to the current OS thread,
which is not a concept we have in GHC.
Yes I'm talking about GHC specifics here, but we want to design an API that
makes sense in multiple settings, and GHC is a setting in which atomic
handlers wouldn't work, I think.
> 3) I hope you will not be deprecating System.Posix.Signals.Exts
> 4) Some signals such as SIGPWR are missing in both 6.8.2 and the new system
Someone should add those to System.Posix.Signals.Exts, yes.
More information about the Libraries