[Mono-dev] Control-C handler
Jonathan Pryor
jonpryor at vt.edu
Wed Jan 9 13:30:41 EST 2008
On Wed, 2008-01-09 at 11:52 -0500, Avery Pennarun wrote:
> On 08/01/2008, Jonathan Pryor <jonpryor at vt.edu> wrote:
> > I don't see why we need a new API to support this. It seems that we
> > could retrofit the existing Stdlib.signal() API to use the
> > implementation you described, with one difference: a runtime internal
> > thread could be used to block on the internal pipe, and when the pipe is
> > readable it could dispatch the appropriate signal via delegate
> > registered with Stdlib.signal(). No polling, and no new public API
> > would be required.
>
> It seems to me that lupus's suggestion is more general than this. In
> other words, you could implement your desired API above on top of his
> without any extra overhead (ie. the overhead is inherent to the
> interface), while you couldn't implement his on top of yours without
> doing a lot of unnecessary work (ie. bouncing into a thread and then
> back again).
Fair point.
> Since mono's signal API is already (presumably) non-standard, it
> should be harmless to correct it by introducing a new nonstandard one
> that works properly.
Now what do you mean by "non-standard," i.e. what's the "standard"
here? .NET? Windows has no signals, so .NET won't expose such a
concept.
On the other hand, the Mono.Unix.Native types have existed for quite
some time and intend to follow the Standard C and POSIX interfaces as
closely as possible. signal(2) is part of the C standard, and is thus
exposed via Stdlib.signal(). It's as standard as you're going to get.
> Note that polling a variable is a fine way to handle signals in many C
> programs. I often write mainloops of the form "while (!want_to_die)",
> where want_to_die is set by my SIGTERM/SIGINT/etc handler. Involving
> a thread for this purpose would be overkill. While this method does
> count as "polling", it is syscall-free polling and only happens at the
> places where you would want to shut down cleanly anyway.
>
> This reminds me, though: what happens to things like socket
> read/write/connect system calls in mono when a signal comes in? In C,
> they get interrupted and return EINTR/EAGAIN, which is why you pop
> back to the mainloop and get a chance to poll your signal variable.
The same thing would happen if you use the low-level Syscall methods --
-1 would be returned and Stdlib.GetLastError() would return Errno.EINTR
or Errno.EAGAIN. The higher-level Mono.Unix types like UnixStream
ignore EINTR.
However, this does raise an interesting problem with a thread-based
approach: since signal dispatching would happen on another thread, there
is no guarantee (and no way to guarantee) that the signal will be
dispatched before the system call returns:
1. Thread 1: Syscall.write()
2. kernel dispatches signal to process
3. Thread 1: Syscall.write() returns -1/EINTR
# some future point in time...
4. Thread 2: Dispatches signal originally raised in (2).
Thread 1 can't safely check e.g. a variable after the EINTR return (in
the normal C fashion) because it might not have been set by the signal
handler yet. It would instead need to wait on a semaphore/condition
variable, which the signal handler could set, to ensure that the threads
are properly synchronized.
On the plus side, the signal handler thread can actually use
semaphores/etc. as it's not running within signal handler context.
So perhaps it would make more sense to expose lupus' approach and layer
Stdlib.signal() atop of it. Though to do that we'd need a better name:
there is already a Mono.Unix.Native.SignalHandler type, and trying to
describe the difference between SignalHandler and UnixSignalHandler is
something I don't look forward to. Perhaps instead:
public class Signal : System.Threading.WaitHandle {
public Signal (Signum signal);
~Signal ();
public Signum Signum { get; }
public bool IsSignaled { get; set; }
}
though the WaitHandle base type might be pure crack (not sure);
regardless, IDisposable should certainly be implemented.
- Jon
More information about the Mono-devel-list
mailing list