RE: Signals + minimal proposal (was Re: asynchronous exceptions)

On 06 April 2006 23:20, John Meacham wrote:
== 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 = ....
-- | register a handler to be run on exiting the program onExit :: IO () -> IO () onExit = ....
-- | block exiting during this call for critical sections. blockExit :: IO a -> IO a blockExit = ...
although thees are less powerful than exceptions in that you can only catch a single event, "exit" they are more powerful in the sense that the exception handlers are global, so when you register an exit handler it happens no matter what thread is in scope.
in addition, an exit_ routine should be added that bypasses the exit handlers, quiting the program immediatly.
I'm not sure I like using exit handlers instead of real exceptions. If the exit handler needs access to some shared mutable state, then it must be sure that the state is not locked when it gets invoked, so all access to the shared state must be protected by blockExit. So all our MVar abstractions will need to use blockExit - but wait, we already use Control.Exception.block in GHC for very similar reasons. And what's more, blockExit suffers from the same problems that we solved with block and interruptible operations: you need to be interruptible while waiting for something (like an MVar), but once it is acquired, the thread should not be interruptible until it has established an exception handler to release the MVar. Exceptions are the right way to handle releasing resources, and they are the right way to register cleanup actions. Therefore I believe exceptions are the right way to handle cleaning up on exit, too. Since async exceptions are no problem to implement in a coop system, shouldn't we use them for exit too? Cheers, Simon

On Fri, Apr 07, 2006 at 01:29:05PM +0100, Simon Marlow wrote:
in addition, an exit_ routine should be added that bypasses the exit handlers, quiting the program immediatly.
I'm not sure I like using exit handlers instead of real exceptions.
If the exit handler needs access to some shared mutable state, then it must be sure that the state is not locked when it gets invoked, so all access to the shared state must be protected by blockExit. So all our MVar abstractions will need to use blockExit - but wait, we already use Control.Exception.block in GHC for very similar reasons. And what's more, blockExit suffers from the same problems that we solved with block and interruptible operations: you need to be interruptible while waiting for something (like an MVar), but once it is acquired, the thread should not be interruptible until it has established an exception handler to release the MVar.
all threads keep running while the exit handers are running, all blockExit would do is grab and release an MVar. exit itself takes that MVar on starting to get rid of races to exit as well as protect itsesf from 'blockExit' (but won't ever put the MVar back). of course, you have to make sure you don't call 'exit' while holding an MVar the handler needs, but that is no problem since your signals happen in their own thread. the only time you would ever need to use blockExit is when you are modifying some unprotected resource an exit handler uses, like some IORefs, even then it strictly isn't necessary because you can just create an MVar for every such resource, but it is not inconcievable you might want to block exiting alltogether. in any case, it can be dropped without affecting utility.
Exceptions are the right way to handle releasing resources, and they are the right way to register cleanup actions. Therefore I believe exceptions are the right way to handle cleaning up on exit, too.
Well, We really need 'onExit' for other reasons as well, I think it should make it into the standard independently. I think you have that backwards, releasing resources is the right thing to do when you get an exception, but there are lots of other reasons you want to release resources that have nothing to do with exceptions. you don't use 'throwTo' to close all your files :)
Since async exceptions are no problem to implement in a coop system, shouldn't we use them for exit too?
but then only one thread gets to clean up after itself, and you have the issue that you can't interrupt a foreign function by throwing to it. exceptions seem like the right way to handle resource relasing from synchronous errors, that occur on a specific thread. but not asynchronous ones, which should not be delivered to any specific thread. Arranging for all your interesting external resources to be managed by some specific thread is not very modular. John -- John Meacham - ⑆repetae.net⑆john⑈
participants (2)
-
John Meacham
-
Simon Marlow