Signals + minimal proposal (was Re: asynchronous exceptions)

David Roundy droundy at darcs.net
Fri Apr 7 08:24:10 EDT 2006


On Thu, Apr 06, 2006 at 03:19:30PM -0700, John Meacham wrote:
> = minimal proposal =
> 
> I think a good minimal solution will be the following, it neatly avoids
> turning signals into exceptions, which may be problematic, but provides
> for the common cases of signal usages while being compatible with both
> cooperative and SMP systems.

I must admit that I don't understand the problem with turning signals into
exceptions, but I really prefer the picture of signals as exceptions, as it
seems to me to be much simpler.  Both simpler to use, and simpler to
describe in the standard.  Rather than having to enumerate (or leave vague)
a list of signals, and describe an API for handling these things that may
or may not exist on a given platform, the standard could just state that
any "OS events that would normally lead to the application quitting"
generate asynchronous exceptions.  This is suitably vague, and has the
result that when coding you can simply assume that bracket will catch
everything that could be caught and lead to nicely cleaning up.  The catch
to this [no pun intended] is that when the main thread exits all other
threads are silently terminated, without the chance to clean up... I'd
prefer they get a special exception first, to give them a chance to clean
up.  But at least with a single-threaded app, you could then work under the
assumption that catching exceptions catches is "complete" (or at least as
complete as the compiler was able to implement--I don't think you can catch
sigKILL, but that's an OS limitation).

> == on exit ==
> 
> implementations also provide an onExit functionality, for registering
> handlers that can be run when the program exits, as this is the most
> common use of signals as exceptions, to clean up after oneself.
> 
> -- | temporarily register an exit handler for the duration of the action argument
> withExitHandler :: IO () -> IO a -> IO a
> withExitHandler = ....

This would work, but seems overly-complex, and leads to interesting
questions.  What happens if the action argument throws an exception? How do
I implement a "really_bracket" using this?

really_bracket init clean job = bracket init clean job'
    where job' a = withExitHandler (do {clean a;return ()}) job

Is this as clean a solution as bracket? It seems to me that in either case
there is a window in which clean won't get called either in the case of a
signal or an exception, although I'm not sure.  I'm also not sure whether
you'd run into danger of clean being called twice when an exit is never
caught, once by the bracket and once by the exit handler.

If signals don't generate exceptions, I'd at least like some sort of
really_bracket to make it into the standard, as this is probably the most
troublesome aspect of existing Haskell.
-- 
David Roundy
http://www.darcs.net


More information about the Haskell-prime mailing list