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

On 06 April 2006 23:20, John Meacham wrote:
I'm not proposing that we ignore signals, just that we should clearly delimit the platform-specific bits, perhaps by putting signal support into an addendum.
yeah, I was thinking a separate environment addendum should be in the report, which takes behavior that is undefined in the language standard, and defines it for various platforms. it wouldn't extend the functionality or scope of the standard, just define what couldn't be defined in the standard.
like the standard might say "the set of signals is undefined" while the UNIX addendum will say "the set of signals will include at least SIGINT,SIGHUP,etc..."
There's the question of whether ^C should look the same on both Windows and Unix. Windows doesn't have signals as such, but some things like ^C can be made to look like signals. We might consider specifying as part of the portable part of the API that there is at least an "interrupt" signal that corresponds to a user interrupt, and in the platform-specific part of the documentation we say what it actually maps to on each platform (SIGINT on Unix, CTRL_BREAK_EVENT on Windows, etc.).
GHC has no support for these right now. They're pretty tricky to handle, because the OS thread that caused the signal to be raised is stopped at some arbitrary instruction, and it would require some serious acrobatics to munge that OS thread into a state where it is possible to raise the (Haskell) exception. I do vaguely recall that people have achieved this in the past, in order to use page faults for write barriers, that sort of thing.
how does ghc handle things like divide by zero then?
By checking before trying to divide :-)
signal an asynchronous exceptional event - the user should be able to choose the threads on which they wish to catch these, those that need to clean up after themselves.
inform the app of an event it might want to take note of - these should run on their own thread, concurrently to all other threads
GHC directly support the latter version, and you can implement the former with a little extra code and a global variable. I think it would be nice to do as you suggest and provide a way to have the async signals turn directly into exceptions.
One problem, though, is that because we can't interrupt a foreign call with an async exception, ^C can be rather unresponsive. Perhaps I should look into this and see whether it would be possible in GHC for a concurrent foreign call to be interruptible; it would involve terminating the foreign call somehow (pthread_cancel?) before raising the exception. We can't do this in a bound thread, however.
You should be able to handle the SIGINT imediatly no matter whether foregin code is running if your handler is in its own thread right?
Yes, but if the signal handler wants to send an exception to the main thread, as it often does, and the main thread is in a foreign call, ^C appears to not do anything.
just have the C signal handler write a byte to a pipe, your haskell signal handler thread is in a
repeatM $ do readExactlyOneByte signalHandler
loop.
Yes, this is exactly what GHC does.
= 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.
== catching signals ==
implementations provide a way of catching signals such that the handler runs as if in its own thread. something like the following
data SigInfo = ... data HandlerType = SigOneShot | SigReset | SigIdempotent
data SigAction = SigAction { signalType :: HandlerType, signalAction :: SigInfo -> IO () } | SigDefault | SigIgnore | SigExit (SigInfo -> ExitStatus)
installHandler :: Signal -> SigAction -> IO SigAction installHandler = ...
the action runs in its own thread.
Yes, looks quite reasonable.
== on exit ==
I'll address this in a separate thread. Cheers, Simon

On Fri, Apr 07, 2006 at 12:36:11PM +0100, Simon Marlow wrote:
You should be able to handle the SIGINT imediatly no matter whether foregin code is running if your handler is in its own thread right?
Yes, but if the signal handler wants to send an exception to the main thread, as it often does, and the main thread is in a foreign call, ^C appears to not do anything.
This is why I proposed the 'onExit' API, since usually you throw the signal to the main thread because that is the one that needs to die and clean up after itself. but if instead you registered your cleanup functions via 'onExit' then there would be no need to have 'throwTo' and the exit handler can run immediatly. no waiting. in some ways it is nicer than rethrowing the exception because any thread can register clean-up handlers, not just the main one. of course, it is only limited to when you actually are quitting the program, but that isn't so bad for the common case and 'onExit' is very useful otherwise. (I curse curses for cursing my terminal into it's occursed state without an exit handler) John -- John Meacham - ⑆repetae.net⑆john⑈
participants (2)
-
John Meacham
-
Simon Marlow