[Mono-dev] Control-C handler

Paolo Molaro lupus at ximian.com
Mon Jan 28 09:25:42 EST 2008


On 01/24/08 Jonathan Pryor wrote:
> After talking on IRC, the sane interface is to provide
> Stdlib.signal_default(), Stdlib.signal_error(), and
> Stdlib.signal_ignore() methods instead of using Stdlib.signal() with

Well, those methods shouldn't be in that namespace and the names
are not really nice.
Ignore maps well to a static Ignore (int signal) method but
I can't come up with a nice name for the other two cases.
An alternative is:
	enum SignalAction {
		Default,
		Ignore,
		Error
	}

and
	static int SetSignalAction (int signum, SignalAction action);

> Index: Mono.Unix/UnixSignal.cs
> ===================================================================
> --- Mono.Unix/UnixSignal.cs	(revision 0)
> +++ Mono.Unix/UnixSignal.cs	(revision 0)
> +using System;
> +using System.Runtime.InteropServices;
> +using System.Threading;
> +
> +using Mono.Unix.Native;
> +
> +namespace Mono.Unix {
> +	public class UnixSignal : WaitHandle {

It should have a finalizer.

> +		private Signum signum;
> +		private int _signum;
> +		private IntPtr signal_info;
> +
> +		public UnixSignal (Signum signum)
> +		{
> +			this.signum = signum;
> +			this._signum = NativeConvert.FromSignum (signum);

There is no need to store reduntant info.

> +		private void AssertValid ()
> +		{
> +			if (signal_info == IntPtr.Zero)
> +				throw new ObjectDisposedException (GetType().FullName);
> +		}
> +
> +		private unsafe SignalInfo* Info {
> +			get {return (SignalInfo*) signal_info;}
> +		}
> +
> +		public bool IsSet {
> +			get {
> +				AssertValid ();
> +				return Count > 0;
> +			}
> +		}
> +
> +		public unsafe bool Reset ()
> +		{
> +			AssertValid ();
> +			int n = Info->count;
> +			Info->count = 0;
> +			return n != 0;
> +		}
> +
> +		public unsafe int Count {
> +			get {return Info->count;}
> +			set {Info->count = value;}

Crashes when Info is NULL.

> +		#region WaitHandle overrides
> +		protected unsafe override void Dispose (bool disposing)
> +		{
> +			if (signal_info == IntPtr.Zero)
> +				return;
> +			uninstall (_signum);
> +			signal_info = IntPtr.Zero;
> +		}

This doesn't implement the documented Dispose pattern.

> Index: signal.c
> ===================================================================
> --- signal.c	(revision 92060)
> +++ signal.c	(working copy)
> @@ -3,18 +3,29 @@
>   *
>   * Authors:
>   *   Jonathan Pryor (jonpryor at vt.edu)
> + *   Jonathan Pryor (jpryor at novell.com)
>   *
>   * Copyright (C) 2004-2005 Jonathan Pryor
> + * Copyright (C) 2008 Novell, Inc.
>   */
>  
>  #include <signal.h>
>  
> +#ifndef PLATFORM_WIN32
> +#include <unistd.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <poll.h>

As reported already the last time, you can't unconditionally use poll.

> @@ -49,6 +61,158 @@
>  	psignal (sig, s);
>  	return errno == 0 ? 0 : -1;
>  }
> +
> +static signal_info signals[64];
> +
> +static inline signal_info*
> +get_info (int signum)
> +{
> +	if (signum < 0 || signum >= sizeof(signals)/sizeof(signals [0]))
> +		return NULL;
> +	return &signals [signum];
> +}
> +
> +static void
> +default_handler (int signum)
> +{
> +	signal_info* h = get_info (signum);
> +	int fd = 0;
> +	if (h) {
> +		++h->count;
> +		if (h->write_fd > 0)
> +			fd = h->write_fd;
> +	}
> +	if (fd) {
> +		char c = signum;
> +		write (fd, &c, 1);
> +	}
> +}
> +
> +static pthread_mutex_t signals_mutex = PTHREAD_MUTEX_INITIALIZER;
> +
> +void*
> +Mono_Unix_UnixSignal_install (int sig)
> +{
> +	int mr;
> +	signal_info* h; 
> +
> +	mr = pthread_mutex_lock (&signals_mutex);
> +	if (mr != 0) {
> +		errno = mr;
> +		return NULL;
> +	}
> +
> +	h = get_info (sig);
> +	if (h == NULL)
> +		errno = EINVAL;
> +	else if (h->have_handler)
> +		errno = EADDRINUSE;
> +	else {
> +		h->count = 0;
> +		h->handler = signal (sig, default_handler);
> +		if (h->handler == SIG_ERR) {
> +			h->handler = NULL;
> +		}
> +		else
> +			h->have_handler = 1;
> +	}
> +
> +	pthread_mutex_unlock (&signals_mutex);
> +
> +	return h;
> +}
> +
> +int
> +Mono_Unix_UnixSignal_uninstall (int sig)

It is important (as in my initialy API sketch) that this function take
the signal_info and not the dignal number, as this implementation allows
only just an handler per signal in the API.

lupus

-- 
-----------------------------------------------------------------
lupus at debian.org                                     debian/rules
lupus at ximian.com                             Monkeys do it better



More information about the Mono-devel-list mailing list