.NET2 handling of exceptions in ThreadPool threads
authorGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Fri, 30 Jul 2010 05:39:43 +0000 (01:39 -0400)
committerGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Fri, 30 Jul 2010 05:54:01 +0000 (01:54 -0400)
* mono/tests/threadpool-exceptions[1-4].cs: new tests
* mono/tests/threadpool.cs: fix typo.
* mono/metadata/threadpool.c: starting in .NET 2.0, unhandled exceptions
in the threadpool can cause a crash in a running program. From now on,
we are compatible.

mono/metadata/threadpool.c
mono/tests/Makefile.am
mono/tests/threadpool-exceptions1.cs [new file with mode: 0644]
mono/tests/threadpool-exceptions2.cs [new file with mode: 0644]
mono/tests/threadpool-exceptions3.cs [new file with mode: 0644]
mono/tests/threadpool-exceptions4.cs [new file with mode: 0644]
mono/tests/threadpool.cs

index 80316a127c7c4876d6fddd7ed9fb670c5d65558f..662697493e971dfc492809aa7fd04d57a36791d1 100755 (executable)
@@ -995,6 +995,8 @@ mono_async_invoke (ThreadPool *tp, MonoAsyncResult *ares)
                void *pa = ares->async_state;
                mono_runtime_delegate_invoke (ares->async_delegate, &pa, &exc);
        } else {
+               MonoObject *cb_exc = NULL;
+
                ac->msg->exc = NULL;
                res = mono_message_invoke (ares->async_delegate, ac->msg, &exc, &out_args);
                MONO_OBJECT_SETREF (ac, res, res);
@@ -1012,13 +1014,13 @@ mono_async_invoke (ThreadPool *tp, MonoAsyncResult *ares)
 
                /* call async callback if cb_method != null*/
                if (ac != NULL && ac->cb_method) {
-                       MonoObject *exc = NULL;
                        void *pa = &ares;
-                       mono_runtime_invoke (ac->cb_method, ac->cb_target, pa, &exc);
-                       /* 'exc' will be the previous ac->msg->exc if not NULL and not
-                        * catched. If catched, this will be set to NULL and the
-                        * exception will not be printed. */
-                       MONO_OBJECT_SETREF (ac->msg, exc, exc);
+                       cb_exc = NULL;
+                       mono_runtime_invoke (ac->cb_method, ac->cb_target, pa, &cb_exc);
+                       MONO_OBJECT_SETREF (ac->msg, exc, cb_exc);
+                       exc = cb_exc;
+               } else {
+                       exc = NULL;
                }
        }
 
@@ -1841,19 +1843,20 @@ async_invoke_thread (gpointer data)
                                }
 
                                if (mono_domain_set (domain, FALSE)) {
-                                       ASyncCall *ac;
+                                       MonoObject *exc;
 
                                        if (tp_item_begin_func)
                                                tp_item_begin_func (tp_item_user_data);
 
                                        if (!is_io_task && ar->add_time > 0)
                                                process_idle_times (tp, ar->add_time);
-                                       mono_async_invoke (tp, ar);
+                                       exc = mono_async_invoke (tp, ar);
                                        if (tp_item_end_func)
                                                tp_item_end_func (tp_item_user_data);
-                                       ac = (ASyncCall *) ar->object_data;
-                                       if (ac && ac->msg && ac->msg->exc != NULL)
-                                               mono_unhandled_exception (ac->msg->exc);
+                                       if (exc && mono_runtime_unhandled_exception_policy_get () == MONO_UNHANDLED_POLICY_CURRENT) {
+                                               mono_unhandled_exception (exc);
+                                               exit (255);
+                                       }
                                        mono_domain_set (mono_get_root_domain (), TRUE);
                                }
                                mono_thread_pop_appdomain_ref ();
index e05ae0c454d77733ff842e0661b8390493b9dc53..66f02beb616cfb5807e6c4b3aed4b5918485d6ff 100644 (file)
@@ -215,6 +215,10 @@ BASE_TEST_CS_SRC=          \
        async_read.cs           \
        threadpool.cs           \
        threadpool1.cs          \
+       threadpool-exceptions1.cs \
+       threadpool-exceptions2.cs \
+       threadpool-exceptions3.cs \
+       threadpool-exceptions4.cs \
        base-definition.cs      \
        bug-27420.cs            \
        bug-47295.cs            \
diff --git a/mono/tests/threadpool-exceptions1.cs b/mono/tests/threadpool-exceptions1.cs
new file mode 100644 (file)
index 0000000..3032de6
--- /dev/null
@@ -0,0 +1,20 @@
+using System;
+using System.Threading;
+
+class Test {
+       static int Main ()
+       {
+               AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
+               ThreadPool.QueueUserWorkItem ((a) => {
+                       throw new Exception ("From the threadpoool");
+                       });
+               Thread.Sleep (1000);
+               return 1;
+       }
+
+       static void OnUnhandledException (object sender, UnhandledExceptionEventArgs e)
+       {
+               Environment.Exit (0);
+       }
+}
+
diff --git a/mono/tests/threadpool-exceptions2.cs b/mono/tests/threadpool-exceptions2.cs
new file mode 100644 (file)
index 0000000..0b12a80
--- /dev/null
@@ -0,0 +1,31 @@
+using System;
+using System.Threading;
+
+class Test {
+       static int return_value = 2;
+       static int Main ()
+       {
+               AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
+               WaitCallback wcb = new WaitCallback ((a) => {
+                       throw new Exception ("From the threadpoool");
+               });
+               wcb.BeginInvoke (wcb, OnCBFinished, null);
+               Thread.Sleep (1000);
+               return 1;
+       }
+
+       static void OnUnhandledException (object sender, UnhandledExceptionEventArgs e)
+       {
+               string str = e.ExceptionObject.ToString ();
+               if (str.IndexOf ("From the threadpool") != -1)
+                       return_value = 3;
+               Environment.Exit (return_value);
+       }
+
+       static void OnCBFinished (object arg)
+       {
+               return_value = 0;
+               throw new Exception ("From OnCBFinished");
+       }
+}
+
diff --git a/mono/tests/threadpool-exceptions3.cs b/mono/tests/threadpool-exceptions3.cs
new file mode 100644 (file)
index 0000000..9f6215c
--- /dev/null
@@ -0,0 +1,21 @@
+using System;
+using System.Threading;
+
+class Test {
+       static int Main ()
+       {
+               AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
+               WaitCallback wcb = new WaitCallback ((a) => {
+                       throw new Exception ("From the threadpoool");
+               });
+               wcb.BeginInvoke (wcb, null, null);
+               Thread.Sleep (1000);
+               return 0;
+       }
+
+       static void OnUnhandledException (object sender, UnhandledExceptionEventArgs e)
+       {
+               Environment.Exit (1);
+       }
+}
+
diff --git a/mono/tests/threadpool-exceptions4.cs b/mono/tests/threadpool-exceptions4.cs
new file mode 100644 (file)
index 0000000..17fa29e
--- /dev/null
@@ -0,0 +1,26 @@
+using System;
+using System.Threading;
+
+class Test {
+       static int Main ()
+       {
+               AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
+               WaitCallback wcb = new WaitCallback ((a) => {
+                       throw new Exception ("From the threadpoool");
+               });
+               wcb.BeginInvoke (wcb, OnCBFinished, null);
+               Thread.Sleep (1000);
+               return 1;
+       }
+
+       static void OnCBFinished (object arg)
+       {
+               throw new Exception ("From OnCBFinished");
+       }
+
+       static void OnUnhandledException (object sender, UnhandledExceptionEventArgs e)
+       {
+               Environment.Exit (0);
+       }
+}
+
index cfcc6ee4c8a256fe1bdcbf724dc684ab8769ae9b..01d3ab9460d90346a5435c7cf4967aa633bac835 100644 (file)
@@ -6,7 +6,7 @@ public class Test {
        static int csum = 0;
        
        public static void test_callback (object state) {
-               Console.WriteLine("test_casllback:" + state);
+               Console.WriteLine("test_callback:" + state);
                Thread.Sleep (200);
                Interlocked.Increment (ref csum);
        }