Treating POSIX signals as exceptions?

John Meacham john at repetae.net
Tue Nov 11 13:29:45 EST 2003


On Mon, Nov 10, 2003 at 10:41:32AM -0500, David Roundy wrote:
> I was wondering why System.Posix.Signals is as it is, and whether it could
> be rewritten to use exceptions, which seems like the obvious way to handle
> signals.  Of course, that requires asynchronous exceptions, but that
> doesn't seem like a severe problem.
> 
> What I currently do is to use the following function
> 
> withSig :: Signal -> IO a -> IO a -> IO a
> withSig s handler job = do
>     id <- myThreadId
>     installHandler s (Catch $ throwDynTo id s) Nothing
>     job `catchDyn` catcher
>         where catcher s' | s' == s = handler
>               catcher s' = throwDyn s'
> 
> which just catches a given signal and throws an exception, and then catches
> that exception with a given default handler.  This has the nice effect that
> my 'job' can't be rudely interrupted by the user hitting ^C at just the
> wrong time (since I use this to catch sigINT).  Thus, this makes bracket
> work in the presence of signals, allows me to use block to avoid being
> interrupted by a ^C when this could cause data corruption, etc.

There is a strong difference between asynchronous signals (like SIGIO,
SIGINT, etc..) and synchronous ones (SIGFPE, SIGSEG). I think only the
second type should be treated as exceptions, since they are tied to a
specific thread of execution. tying asynchronous signals to exceptions
just because they are posted to the program in the same way seems wrong.
especially when we have concurrency. registering a callback, or even
having a 'wait' like thing to blockingly wait for the next asynchronous
signal would be ideal. 

note that the POSIX real-time (and threading) specifications make the
distinction between the two signal types and handle them differently so
there is precidence.

> (Yes, I know that the above isn't very clean, since any other process that
> uses {catch,throw}Dyn on a CInt will mess things up, but creating a new
> Typeable instance seemed like too much trouble.)
> 
> Is there any reason all of System.Posix.Signals couldn't be done in this
> manner? Have the RTS always add a handler for each signal, which just
> throws an exception.  Off the top of my head, all we'd need is one function

well, we would want to ignore many signals for one thing. once an
exception is thrown, it is hard to 'un-throw'. (although, if someone
invented a way to do it, that would be groovy..)

> acceptSignals :: IO () -- tells RTS to send signal exceptions to this
>                        -- thread.
> 
> We'd also need some sort of SignalException type (and of course, to define
> all the signals), and the rest would be done using the existing
> Control.Exception code.  And, of course, default signal handlers would need
> to be converted to default exception handlers.

we need some data type which contains the information in the 'siginfo_t'
structure. then we can include this as a standard Exception type for use
with synchronous signals.

-- 
---------------------------------------------------------------------------
John Meacham - California Institute of Technology, Alum. - john at foo.net
---------------------------------------------------------------------------


More information about the Haskell-Cafe mailing list