Fixed the console sigint deadlock, by queuing execution in the finalizer thread.
authorPaolo Molaro <lupus@oddwiz.org>
Tue, 12 Oct 2010 15:08:42 +0000 (17:08 +0200)
committerPaolo Molaro <lupus@oddwiz.org>
Tue, 12 Oct 2010 15:08:42 +0000 (17:08 +0200)
* console-io.h, console-null.c, console-unix.c, console-win32.c,
gc.c: instead of executing tons of managed code in signal context,
we wake up the finalizer thread and any complex console-specific
code will be handled there. This can cause a (usually small) delay,
but it's much better than deadlocking.

mono/metadata/console-io.h
mono/metadata/console-null.c
mono/metadata/console-unix.c
mono/metadata/console-win32.c
mono/metadata/gc.c

index 46bfe44aaef70942dbb40926e85d8ea178198700..a7ef7686b68930b69490f9879aa3bcd371e566f9 100644 (file)
@@ -19,6 +19,7 @@
 G_BEGIN_DECLS
 
 void mono_console_init (void) MONO_INTERNAL;
+void mono_console_handle_async_ops (void) MONO_INTERNAL;
 MonoBoolean ves_icall_System_ConsoleDriver_Isatty (HANDLE handle) MONO_INTERNAL;
 gint32 ves_icall_System_ConsoleDriver_InternalKeyAvailable (gint32 timeout) MONO_INTERNAL;
 MonoBoolean ves_icall_System_ConsoleDriver_SetEcho (MonoBoolean echo) MONO_INTERNAL;
index a50b2a37d203ecfc99e593b20a4fda0180e48fe6..a2e1486c084d07f774d19dbcc8873cb4dfbfc7bf 100644 (file)
@@ -11,6 +11,7 @@
 #include <mono/metadata/object-internals.h>
 #include <mono/metadata/class-internals.h>
 #include <mono/metadata/domain-internals.h>
+#include <mono/metadata/gc-internal.h>
 
 #include <mono/metadata/console-io.h>
 #include <mono/metadata/exception.h>
@@ -20,6 +21,11 @@ mono_console_init (void)
 {
 }
 
+void
+mono_console_handle_async_ops (void)
+{
+}
+
 MonoBoolean
 ves_icall_System_ConsoleDriver_Isatty (HANDLE handle)
 {
index a6c86d1271895e077dc0eee71d04d678236986e3..aae513f1a021197c25473d61f3a080ae64396577 100644 (file)
@@ -28,6 +28,7 @@
 #include <mono/metadata/object-internals.h>
 #include <mono/metadata/class-internals.h>
 #include <mono/metadata/domain-internals.h>
+#include <mono/metadata/gc-internal.h>
 #include <mono/metadata/metadata.h>
 #include <mono/metadata/threadpool.h>
 
@@ -231,6 +232,7 @@ do_console_cancel_event (void)
        MonoMethod *im;
        MonoVTable *vtable;
 
+       /* FIXME: this should likely iterate all the domains, instead */
        if (!domain->domain)
                return;
 
@@ -258,6 +260,17 @@ do_console_cancel_event (void)
        mono_thread_pool_add ((MonoObject *) load_value, msg, NULL, NULL);
 }
 
+static int need_cancel = FALSE;
+/* this is executed from the finalizer thread */
+void
+mono_console_handle_async_ops (void)
+{
+       if (need_cancel) {
+               need_cancel = FALSE;
+               do_console_cancel_event ();
+       }
+}
+
 static gboolean in_sigint;
 static void
 sigint_handler (int signo)
@@ -270,7 +283,8 @@ sigint_handler (int signo)
 
        in_sigint = TRUE;
        save_errno = errno;
-       do_console_cancel_event ();
+       need_cancel = TRUE;
+       mono_gc_finalize_notify ();
        errno = save_errno;
        in_sigint = FALSE;
 }
index 561809917968915a76a223bc9f01016d8b6350e6..6b940f3edfb4e85920a526d0cc56a6fa868e273f 100644 (file)
@@ -24,6 +24,7 @@
 #include <mono/metadata/object-internals.h>
 #include <mono/metadata/class-internals.h>
 #include <mono/metadata/domain-internals.h>
+#include <mono/metadata/gc-internal.h>
 #include <mono/metadata/metadata.h>
 #include <mono/metadata/threadpool.h>
 
@@ -35,6 +36,11 @@ mono_console_init (void)
 {
 }
 
+void
+mono_console_handle_async_ops (void)
+{
+}
+
 MonoBoolean
 ves_icall_System_ConsoleDriver_Isatty (HANDLE handle)
 {
index 718fdbf05e7481e9ee5fe903e6c9333ea9a11dfd..83064485e73f9d4c0f110baeefd8177dac92ee53 100644 (file)
@@ -27,6 +27,7 @@
 #include <mono/metadata/gc-internal.h>
 #include <mono/metadata/marshal.h> /* for mono_delegate_free_ftnptr () */
 #include <mono/metadata/attach.h>
+#include <mono/metadata/console-io.h>
 #include <mono/utils/mono-semaphore.h>
 
 #ifndef HOST_WIN32
@@ -1043,6 +1044,8 @@ finalizer_thread (gpointer unused)
                WaitForSingleObjectEx (finalizer_event, INFINITE, FALSE);
 #endif
 
+               mono_console_handle_async_ops ();
+
 #ifndef DISABLE_ATTACH
                mono_attach_maybe_start ();
 #endif