[Mono-dev] [RFC v5 3/7] Handle lack of SA_SIGINFO on Haiku

Andreas Färber andreas.faerber at web.de
Sun Apr 4 19:52:17 EDT 2010


SA_SIGINFO-style signals were part of the POSIX.1-2006 optional
Real Time Signals (XSI RTS) feature. Haiku does not implement it (yet)
and goes so far as to not define SA_SIGINFO to indicate lack thereof.

In POSIX.1-2008 they're no longer optional. Define SA_SIGINFO for Haiku,
to avoid a forest of #ifdefs in Mono code. As long as Haiku doesn't
support it, all sa_flags checks for SA_SIGINFO will evaluate to false,
leading to the right code path taken.

In console-unix, don't assume SA_SIGINFO signal handler parameters or
chained SA_SIGINFO signal handlers. To cope with SA_SIGINFO chaining,
request SA_SIGINFO semantics if available. Handle both types of chained
signal handlers.

Fixes build on Haiku.

Cc: Miguel de Icaza <miguel at novell.com>
Cc: Paolo Molaro <lupus at ximian.com>
Cc: Ingo Weinhold <ingo_weinhold at gmx.de>

v4 -> v5:
* Add support for chained BeOS-style signal handlers.
* Drop mini changes, define SA_SIGINFO in configure instead.
* Decouple local MONO_ARCH_USE_SIGACTION from SA_SIGINFO (FIXME).

v3 -> v4:
* Replace macro with inline function, requested by Miguel de Icaza.
* Don't assume SA_SIGINFO, request it explicitly, if possible.

v2 -> v3:
* Rework signature macros to match mini.

v1 -> v2:
* Introduce helper macros, suggested by Paolo Molaro.

This commit is licensed under the MIT X11 license.
---
 ChangeLog                    |    6 +++
 configure.in                 |    2 +
 mono/metadata/ChangeLog      |    9 +++++
 mono/metadata/console-unix.c |   83 +++++++++++++++++++++++++++++++++++++-----
 4 files changed, 90 insertions(+), 10 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index bb8ef4b..c97f411 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2010-04-04  Andreas Färber  <andreas.faerber at web.de>
 
+	* configure.in: Define SA_SIGINFO for Haiku.
+
+	Contributed under MIT/X11 license.
+
+2010-04-04  Andreas Färber  <andreas.faerber at web.de>
+
 	* configure.in: Fix typo.
 	Set default for with_moonlight to fix "Moon Profile:" output.
 
diff --git a/configure.in b/configure.in
index bc9e755..5e34fc4 100644
--- a/configure.in
+++ b/configure.in
@@ -266,6 +266,8 @@ case "$host" in
 	*-*-haiku*)
 		host_win32=no
 		CPPFLAGS="$CPPFLAGS -D_REENTRANT -D_THREAD_SAFE"
+		# SA_SIGINFO is currently commented out in Haiku's headers
+		CPPFLAGS="$CPPFLAGS -DSA_SIGINFO=0x40"
 		libmono_cflags="-D_REENTRANT -D_THREAD_SAFE"
 		libdl=
 		LIBS="$LIBS -lnetwork"
diff --git a/mono/metadata/ChangeLog b/mono/metadata/ChangeLog
index 2d076da..0aaf44c 100644
--- a/mono/metadata/ChangeLog
+++ b/mono/metadata/ChangeLog
@@ -1,3 +1,12 @@
+2010-04-04  Andreas Färber  <andreas.faerber at web.de>
+
+	* console-unix.c (sigcont_handler, sigwinch_handler): Don't assume
+	SA_SIGINFO-style signals. Fixes the build on platforms without (Haiku).
+	(console_set_signal_handlers): Distinguish between SA_SIGINFO and
+	default signal handlers to match our signal handlers' expectations.
+
+	Code is contributed under MIT/X11 license.
+
 2010-04-04  Mark Probst  <mark.probst at gmail.com>
 
 	* sgen-gc.c: Remove superfluous scanning of alloc-pinned objects.
diff --git a/mono/metadata/console-unix.c b/mono/metadata/console-unix.c
index 0845c64..01e7742 100644
--- a/mono/metadata/console-unix.c
+++ b/mono/metadata/console-unix.c
@@ -246,6 +246,65 @@ do_console_cancel_event (void)
 	mono_thread_pool_add ((MonoObject *) load_value, msg, NULL, NULL);
 }
 
+
+#define SIGHANDLER_SIGNATURE_SIGACTION	int signo, void *the_siginfo, void *data
+#define SIGHANDLER_PARAMS_SIGACTION	signo, the_siginfo, data
+#if defined(__HAIKU__)
+#define SIGHANDLER_SIGNATURE_HANDLER	int signo, char *userData, vregs regs
+#define SIGHANDLER_PARAMS_HANDLER	signo, userData, regs
+#else
+#define SIGHANDLER_SIGNATURE_HANDLER	int signo
+#define SIGHANDLER_PARAMS_HANDLER	signo
+#endif
+
+/* FIXME: move MONO_ARCH_USE_SIGACTION to central header? */
+#if !defined(__HAIKU__)
+#define MONO_ARCH_USE_SIGACTION
+#endif
+
+/* SIG_HANDLER_SIGNATURE and SIG_HANDLER_PARAMS synchronized with mini */
+#ifdef MONO_ARCH_USE_SIGACTION
+#define SIGHANDLER_SIGNATURE SIGHANDLER_SIGNATURE_SIGACTION
+#define SIG_HANDLER_PARAMS SIGHANDLER_PARAMS_SIGACTION
+#else
+#define SIGHANDLER_SIGNATURE SIGHANDLER_SIGNATURE_HANDLER
+#define SIG_HANDLER_PARAMS SIGHANDLER_PARAMS_HANDLER
+#endif
+#define SIG_HANDLER_SIGNATURE(ftn) ftn (SIGHANDLER_SIGNATURE)
+
+static inline gboolean
+is_sighandler_valid (void *sigh)
+{
+	return sigh != NULL &&
+		sigh != (void *)SIG_DFL &&
+		sigh != (void *)SIG_IGN;
+}
+
+static inline void
+invoke_sighandler_if_valid (struct sigaction *siga, SIGHANDLER_SIGNATURE)
+{
+	if (siga->sa_flags & SA_SIGINFO) {
+#ifdef MONO_ARCH_USE_SIGACTION
+		if (is_sighandler_valid (siga->sa_sigaction))
+			(*siga->sa_sigaction) (SIGHANDLER_PARAMS_SIGACTION);
+#endif
+	} else {
+		if (is_sighandler_valid (siga->sa_handler))
+#if (defined(__HAIKU__)) && defined(MONO_ARCH_USE_SIGACTION)
+			(*siga->sa_handler) (signo, NULL/*XXX*/,
+				*((ucontext_t *)data)->uc_mcontext/*XXX*/);
+#elif defined(__HAIKU__)
+			(*(void (*) (int, char *, vregs))siga->sa_handler) (SIGHANDLER_PARAMS_HANDLER);
+#else
+			(*siga->sa_handler) (SIGHANDLER_PARAMS_HANDLER);
+#endif
+	}
+}
+
+#define INVOKE_SIGHANDLER_IF_VALID(siga) \
+	invoke_sighandler_if_valid (&(siga), SIG_HANDLER_PARAMS)
+
+
 static gboolean in_sigint;
 static void
 sigint_handler (int signo)
@@ -263,7 +322,7 @@ sigint_handler (int signo)
 static struct sigaction save_sigcont, save_sigint, save_sigwinch;
 
 static void
-sigcont_handler (int signo, void *the_siginfo, void *data)
+SIG_HANDLER_SIGNATURE (sigcont_handler)
 {
 	// Ignore error, there is not much we can do in the sigcont handler.
 	tcsetattr (STDIN_FILENO, TCSANOW, &mono_attr);
@@ -272,24 +331,18 @@ sigcont_handler (int signo, void *the_siginfo, void *data)
 		write (STDOUT_FILENO, keypad_xmit_str, strlen (keypad_xmit_str));
 
 	// Call previous handler
-	if (save_sigcont.sa_sigaction != NULL &&
-	    save_sigcont.sa_sigaction != (void *)SIG_DFL &&
-	    save_sigcont.sa_sigaction != (void *)SIG_IGN)
-		(*save_sigcont.sa_sigaction) (signo, the_siginfo, data);
+	INVOKE_SIGHANDLER_IF_VALID (save_sigcont);
 }
 
 static void
-sigwinch_handler (int signo, void *the_siginfo, void *data)
+SIG_HANDLER_SIGNATURE (sigwinch_handler)
 {
 	int dims = terminal_get_dimensions ();
 	if (dims != -1)
 		cols_and_lines = dims;
 	
 	// Call previous handler
-	if (save_sigwinch.sa_sigaction != NULL &&
-	    save_sigwinch.sa_sigaction != (void *)SIG_DFL &&
-	    save_sigwinch.sa_sigaction != (void *)SIG_IGN)
-		(*save_sigwinch.sa_sigaction) (signo, the_siginfo, data);
+	INVOKE_SIGHANDLER_IF_VALID (save_sigwinch);
 }
 
 void
@@ -302,8 +355,13 @@ console_set_signal_handlers ()
 	memset (&sigwinch, 0, sizeof (struct sigaction));
 	
 	// Continuing
+#ifdef MONO_ARCH_USE_SIGACTION
+	sigcont.sa_sigaction = (void *) sigcont_handler;
+	sigcont.sa_flags = SA_SIGINFO;
+#else
 	sigcont.sa_handler = (void *) sigcont_handler;
 	sigcont.sa_flags = 0;
+#endif
 	sigemptyset (&sigcont.sa_mask);
 	sigaction (SIGCONT, &sigcont, &save_sigcont);
 	
@@ -314,8 +372,13 @@ console_set_signal_handlers ()
 	sigaction (SIGINT, &sigint, &save_sigint);
 
 	// Window size changed
+#ifdef MONO_ARCH_USE_SIGACTION
+	sigwinch.sa_sigaction = (void *) sigwinch_handler;
+	sigwinch.sa_flags = SA_SIGINFO;
+#else
 	sigwinch.sa_handler = (void *) sigwinch_handler;
 	sigwinch.sa_flags = 0;
+#endif
 	sigemptyset (&sigwinch.sa_mask);
 	sigaction (SIGWINCH, &sigwinch, &save_sigwinch);
 }
-- 
1.7.0.4.297.g6555b1



More information about the Mono-devel-list mailing list