2009-09-25 Rolf Bjarne Kvinge <RKvinge@novell.com>
authorRolf Bjarne Kvinge <RKvinge@novell.com>
Fri, 25 Sep 2009 21:13:54 +0000 (21:13 -0000)
committerRolf Bjarne Kvinge <RKvinge@novell.com>
Fri, 25 Sep 2009 21:13:54 +0000 (21:13 -0000)
* appdomain.c|h: Add a mono_domain_try_unload method which is
equivalent to mono_domain_unload, except that it returns an exception
instead of throwing it. Make mono_domain_unload use the
mono_domain_try_unload method to avoid code-duplication.

svn path=/trunk/mono/; revision=142658

mono/metadata/ChangeLog
mono/metadata/appdomain.c
mono/metadata/appdomain.h

index 8eb8c5aad06527557673ad7ea0a94245d8a729d4..a825c2ea0a02fca23770875620960624f207517f 100644 (file)
@@ -1,3 +1,10 @@
+2009-09-25  Rolf Bjarne Kvinge  <RKvinge@novell.com>
+
+       * appdomain.c|h: Add a mono_domain_try_unload method which is
+       equivalent to mono_domain_unload, except that it returns an exception
+       instead of throwing it. Make mono_domain_unload use the
+       mono_domain_try_unload method to avoid code-duplication.
+
 2009-09-25  Zoltan Varga  <vargaz@gmail.com>
 
        * debug-helpers.c (dis_one): Avoid unaligned accesses on platforms where that is
index 2858dd77e41137b02b0842e22ca24f54a68eda44..c4a3b31be7508a70150370612c8a50eb80a5326f 100644 (file)
@@ -2103,22 +2103,45 @@ unload_thread_main (void *arg)
  * mono_domain_unload:
  * @domain: The domain to unload
  *
+ *  Unloads an appdomain. Follows the process outlined in the comment
+ *  for mono_domain_try_unload.
+ */
+void
+mono_domain_unload (MonoDomain *domain)
+{
+       MonoObject *exc = NULL;
+       mono_domain_try_unload (domain, &exc);
+       if (exc)
+               mono_raise_exception ((MonoException*)exc);
+}
+
+/*
+ * mono_domain_unload:
+ * @domain: The domain to unload
+ * @exc: Exception information
+ *
  *  Unloads an appdomain. Follows the process outlined in:
  *  http://blogs.gotdotnet.com/cbrumme
  *
  *  If doing things the 'right' way is too hard or complex, we do it the 
  *  'simple' way, which means do everything needed to avoid crashes and
  *  memory leaks, but not much else.
+ *
+ *  It is required to pass a valid reference to the exc argument, upon return
+ *  from this function *exc will be set to the exception thrown, if any.
+ *
+ *  If this method is not called from an icall (embedded scenario for instance),
+ *  it must not be called with any managed frames on the stack, since the unload
+ *  process could end up trying to abort the current thread.
  */
 void
-mono_domain_unload (MonoDomain *domain)
+mono_domain_try_unload (MonoDomain *domain, MonoObject **exc)
 {
        HANDLE thread_handle;
        gsize tid;
        guint32 res;
        MonoAppDomainState prev_state;
        MonoMethod *method;
-       MonoObject *exc;
        unload_data thread_data;
        MonoDomain *caller_domain = mono_domain_get ();
 
@@ -2132,11 +2155,11 @@ mono_domain_unload (MonoDomain *domain)
                switch (prev_state) {
                case MONO_APPDOMAIN_UNLOADING_START:
                case MONO_APPDOMAIN_UNLOADING:
-                       mono_raise_exception (mono_get_exception_cannot_unload_appdomain ("Appdomain is already being unloaded."));
-                       break;
+                       *exc = (MonoObject *) mono_get_exception_cannot_unload_appdomain ("Appdomain is already being unloaded.");
+                       return;
                case MONO_APPDOMAIN_UNLOADED:
-                       mono_raise_exception (mono_get_exception_cannot_unload_appdomain ("Appdomain is already unloaded."));
-                       break;
+                       *exc = (MonoObject *) mono_get_exception_cannot_unload_appdomain ("Appdomain is already unloaded.");
+                       return;
                default:
                        g_warning ("Incalid appdomain state %d", prev_state);
                        g_assert_not_reached ();
@@ -2150,13 +2173,12 @@ mono_domain_unload (MonoDomain *domain)
        method = mono_class_get_method_from_name (domain->domain->mbr.obj.vtable->klass, "DoDomainUnload", -1); 
        g_assert (method);
 
-       exc = NULL;
-       mono_runtime_invoke (method, domain->domain, NULL, &exc);
-       if (exc) {
+       mono_runtime_invoke (method, domain->domain, NULL, exc);
+       if (*exc) {
                /* Roll back the state change */
                domain->state = MONO_APPDOMAIN_CREATED;
                mono_domain_set (caller_domain, FALSE);
-               mono_raise_exception ((MonoException*)exc);
+               return;
        }
        mono_domain_set (caller_domain, FALSE);
 
@@ -2195,18 +2217,14 @@ mono_domain_unload (MonoDomain *domain)
        CloseHandle (thread_handle);
 
        if (thread_data.failure_reason) {
-               MonoException *ex;
-
                /* Roll back the state change */
                domain->state = MONO_APPDOMAIN_CREATED;
 
                g_warning ("%s", thread_data.failure_reason);
 
-               ex = mono_get_exception_cannot_unload_appdomain (thread_data.failure_reason);
+               *exc = (MonoObject *) mono_get_exception_cannot_unload_appdomain (thread_data.failure_reason);
 
                g_free (thread_data.failure_reason);
                thread_data.failure_reason = NULL;
-
-               mono_raise_exception (ex);
        }
 }
index e4da4e4404bb0df47065cb1820d3ec3124295b64..4ec0cc28764a5f01912f3d170569583c0cc00004 100644 (file)
@@ -85,6 +85,9 @@ mono_domain_set_internal   (MonoDomain *domain);
 void
 mono_domain_unload (MonoDomain *domain);
 
+void
+mono_domain_try_unload (MonoDomain *domain, MonoObject **exc);
+
 gboolean
 mono_domain_is_unloading   (MonoDomain *domain);