Merge pull request #3093 from lambdageek/dev/monoerror-exec
authorAleksey Kliger (λgeek) <akliger@gmail.com>
Wed, 8 Jun 2016 14:35:46 +0000 (10:35 -0400)
committerAleksey Kliger (λgeek) <akliger@gmail.com>
Wed, 8 Jun 2016 14:35:46 +0000 (10:35 -0400)
[runtime] Mark mono_runtime_{run,exec}_main external only.

mono/metadata/appdomain.c
mono/metadata/coree.c
mono/metadata/object-internals.h
mono/metadata/object.c
mono/metadata/object.h
mono/mini/driver.c

index eb3f68204036d2f79ab525c3995a8a3a689867e4..9bd5f0f645c4eaf3f1957382f3b9377447c4d2a1 100644 (file)
@@ -2235,7 +2235,9 @@ ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomain *ad,
                mono_error_assert_ok (&error);
        }
 
-       return mono_runtime_exec_main (method, (MonoArray *)args, NULL);
+       int res = mono_runtime_exec_main_checked (method, (MonoArray *)args, &error);
+       mono_error_set_pending_exception (&error);
+       return res;
 }
 
 gint32 
index 326251cc140c53a575ff7e227abcdeea92bc2782..f0e2f0d58c8fcbf1fdc89d337f116e67a0376762 100644 (file)
@@ -197,7 +197,8 @@ __int32 STDMETHODCALLTYPE _CorExeMain(void)
                argv [i] = g_utf16_to_utf8 (argvw [i], -1, NULL, NULL, NULL);
        LocalFree (argvw);
 
-       mono_runtime_run_main (method, argc, argv, NULL);
+       mono_runtime_run_main_checked (method, argc, argv, &error);
+       mono_error_raise_exception (&error); /* FIXME don't raise here */
        mono_thread_manage ();
 
        mono_runtime_quit ();
index 3bab96e4e59d55be5a8e550fc4bfddd47e93a8bd..ee0f6ab546ab55a4c933df452df3add21e567ed2 100644 (file)
@@ -1740,6 +1740,21 @@ mono_runtime_delegate_invoke_checked (MonoObject *delegate, void **params,
 MonoArray*
 mono_runtime_get_main_args_checked (MonoError *error);
 
+int
+mono_runtime_run_main_checked (MonoMethod *method, int argc, char* argv[],
+                              MonoError *error);
+
+int
+mono_runtime_try_run_main (MonoMethod *method, int argc, char* argv[],
+                          MonoObject **exc, MonoError *error);
+
+int
+mono_runtime_exec_main_checked (MonoMethod *method, MonoArray *args, MonoError *error);
+
+int
+mono_runtime_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc, MonoError *error);
+
+
 #endif /* __MONO_OBJECT_INTERNALS_H__ */
 
 
index a9006ac4889c277a88b4f44540d6556a6739b96f..7e4c9dc4e062b84777f32afaf1ab51e5ddd3ea04 100644 (file)
@@ -4165,22 +4165,14 @@ mono_runtime_set_main_args (int argc, char* argv[])
        return 0;
 }
 
-/**
- * mono_runtime_run_main:
- * @method: the method to start the application with (usually Main)
- * @argc: number of arguments from the command line
- * @argv: array of strings from the command line
- * @exc: excetption results
- *
- * Execute a standard Main() method (argc/argv contains the
- * executable name). This method also sets the command line argument value
- * needed by System.Environment.
- *
+/*
+ * Prepare an array of arguments in order to execute a standard Main()
+ * method (argc/argv contains the executable name). This method also
+ * sets the command line argument value needed by System.Environment.
  * 
  */
-int
-mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
-                      MonoObject **exc)
+static MonoArray*
+prepare_run_main (MonoMethod *method, int argc, char *argv[])
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
@@ -4271,9 +4263,92 @@ mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
        
        mono_assembly_set_main (method->klass->image->assembly);
 
-       return mono_runtime_exec_main (method, args, exc);
+       return args;
+}
+
+/**
+ * mono_runtime_run_main:
+ * @method: the method to start the application with (usually Main)
+ * @argc: number of arguments from the command line
+ * @argv: array of strings from the command line
+ * @exc: excetption results
+ *
+ * Execute a standard Main() method (argc/argv contains the
+ * executable name). This method also sets the command line argument value
+ * needed by System.Environment.
+ *
+ * 
+ */
+int
+mono_runtime_run_main (MonoMethod *method, int argc, char* argv[],
+                      MonoObject **exc)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       MonoError error;
+       MonoArray *args = prepare_run_main (method, argc, argv);
+       int res;
+       if (exc) {
+               res = mono_runtime_try_exec_main (method, args, exc, &error);
+               if (*exc == NULL && !is_ok (&error))
+                       *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+               else
+                       mono_error_cleanup (&error);
+       } else {
+               res = mono_runtime_exec_main_checked (method, args, &error);
+               mono_error_raise_exception (&error); /* OK to throw, external only without a better alternative */
+       }
+       return res;
+}
+
+/**
+ * mono_runtime_run_main_checked:
+ * @method: the method to start the application with (usually Main)
+ * @argc: number of arguments from the command line
+ * @argv: array of strings from the command line
+ * @error: set on error
+ *
+ * Execute a standard Main() method (argc/argv contains the
+ * executable name). This method also sets the command line argument value
+ * needed by System.Environment.  On failure sets @error.
+ *
+ * 
+ */
+int
+mono_runtime_run_main_checked (MonoMethod *method, int argc, char* argv[],
+                              MonoError *error)
+{
+       mono_error_init (error);
+       MonoArray *args = prepare_run_main (method, argc, argv);
+       return mono_runtime_exec_main_checked (method, args, error);
+}
+
+/**
+ * mono_runtime_try_run_main:
+ * @method: the method to start the application with (usually Main)
+ * @argc: number of arguments from the command line
+ * @argv: array of strings from the command line
+ * @exc: set if Main throws an exception
+ * @error: set if Main can't be executed
+ *
+ * Execute a standard Main() method (argc/argv contains the executable
+ * name). This method also sets the command line argument value needed
+ * by System.Environment.  On failure sets @error if Main can't be
+ * executed or @exc if it threw and exception.
+ *
+ * 
+ */
+int
+mono_runtime_try_run_main (MonoMethod *method, int argc, char* argv[],
+                          MonoObject **exc, MonoError *error)
+{
+       g_assert (exc);
+       mono_error_init (error);
+       MonoArray *args = prepare_run_main (method, argc, argv);
+       return mono_runtime_try_exec_main (method, args, exc, error);
 }
 
+
 static MonoObject*
 serialize_object (MonoObject *obj, gboolean *failure, MonoObject **exc)
 {
@@ -4632,28 +4707,13 @@ mono_runtime_exec_managed_code (MonoDomain *domain,
        mono_thread_manage ();
 }
 
-/*
- * Execute a standard Main() method (args doesn't contain the
- * executable name).
- */
-int
-mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
+static void
+prepare_thread_to_exec_main (MonoDomain *domain, MonoMethod *method)
 {
-       MONO_REQ_GC_UNSAFE_MODE;
-
-       MonoError error;
-       MonoDomain *domain;
-       gpointer pa [1];
-       int rval;
+       MonoInternalThread* thread = mono_thread_internal_current ();
        MonoCustomAttrInfo* cinfo;
        gboolean has_stathread_attribute;
-       MonoInternalThread* thread = mono_thread_internal_current ();
 
-       g_assert (args);
-
-       pa [0] = args;
-
-       domain = mono_object_domain (args);
        if (!domain->entry_assembly) {
                gchar *str;
                MonoAssembly *assembly;
@@ -4673,8 +4733,9 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
                }
        }
 
-       cinfo = mono_custom_attrs_from_method_checked (method, &error);
-       mono_error_cleanup (&error); /* FIXME warn here? */
+       MonoError cattr_error;
+       cinfo = mono_custom_attrs_from_method_checked (method, &cattr_error);
+       mono_error_cleanup (&cattr_error); /* FIXME warn here? */
        if (cinfo) {
                has_stathread_attribute = mono_custom_attrs_has_attr (cinfo, mono_class_get_sta_thread_attribute_class ());
                if (!cinfo->cached)
@@ -4689,39 +4750,85 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
        }
        mono_thread_init_apartment_state ();
 
+}
+
+static int
+do_exec_main_checked (MonoMethod *method, MonoArray *args, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       gpointer pa [1];
+       int rval;
+
+       mono_error_init (error);
+       g_assert (args);
+
+       pa [0] = args;
+
        /* FIXME: check signature of method */
        if (mono_method_signature (method)->ret->type == MONO_TYPE_I4) {
                MonoObject *res;
-               if (exc) {
-                       res = mono_runtime_try_invoke (method, NULL, pa, exc, &error);
-                       if (*exc == NULL && !mono_error_ok (&error))
-                               *exc = (MonoObject*) mono_error_convert_to_exception (&error);
-                       else
-                               mono_error_cleanup (&error);
-               } else {
-                       res = mono_runtime_invoke_checked (method, NULL, pa, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
+               res = mono_runtime_invoke_checked (method, NULL, pa, error);
+               if (is_ok (error))
+                       rval = *(guint32 *)((char *)res + sizeof (MonoObject));
+               else
+                       rval = -1;
+               mono_environment_exitcode_set (rval);
+       } else {
+               mono_runtime_invoke_checked (method, NULL, pa, error);
+
+               if (is_ok (error))
+                       rval = 0;
+               else {
+                       /* If the return type of Main is void, only
+                        * set the exitcode if an exception was thrown
+                        * (we don't want to blow away an
+                        * explicitly-set exit code)
+                        */
+                       rval = -1;
+                       mono_environment_exitcode_set (rval);
                }
+       }
+       return rval;
+}
+
+static int
+do_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc, MonoError *error)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+
+       gpointer pa [1];
+       int rval;
+
+       mono_error_init (error);
+       g_assert (args);
+       g_assert (exc);
+
+       pa [0] = args;
+
+       /* FIXME: check signature of method */
+       if (mono_method_signature (method)->ret->type == MONO_TYPE_I4) {
+               MonoObject *res;
+               res = mono_runtime_try_invoke (method, NULL, pa, exc, error);
+               if (*exc == NULL && !mono_error_ok (error))
+                       *exc = (MonoObject*) mono_error_convert_to_exception (error);
+               else
+                       mono_error_cleanup (error);
 
-               if (!exc || !*exc)
+               if (*exc == NULL)
                        rval = *(guint32 *)((char *)res + sizeof (MonoObject));
                else
                        rval = -1;
 
                mono_environment_exitcode_set (rval);
        } else {
-               if (exc) {
-                       mono_runtime_try_invoke (method, NULL, pa, exc, &error);
-                       if (*exc == NULL && !mono_error_ok (&error))
-                               *exc = (MonoObject*) mono_error_convert_to_exception (&error);
-                       else
-                               mono_error_cleanup (&error);
-               } else {
-                       mono_runtime_invoke_checked (method, NULL, pa, &error);
-                       mono_error_raise_exception (&error); /* FIXME don't raise here */
-               }
+               mono_runtime_try_invoke (method, NULL, pa, exc, error);
+               if (*exc == NULL && !mono_error_ok (error))
+                       *exc = (MonoObject*) mono_error_convert_to_exception (error);
+               else
+                       mono_error_cleanup (error);
 
-               if (!exc || !*exc)
+               if (*exc == NULL)
                        rval = 0;
                else {
                        /* If the return type of Main is void, only
@@ -4737,6 +4844,59 @@ mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
        return rval;
 }
 
+/*
+ * Execute a standard Main() method (args doesn't contain the
+ * executable name).
+ */
+int
+mono_runtime_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc)
+{
+       MonoError error;
+       prepare_thread_to_exec_main (mono_object_domain (args), method);
+       if (exc) {
+               int rval = do_try_exec_main (method, args, exc, &error);
+               if (*exc == NULL && !is_ok (&error))
+                       *exc = (MonoObject*) mono_error_convert_to_exception (&error);
+               else
+                       mono_error_cleanup (&error);
+               return rval;
+       } else {
+               int rval = do_exec_main_checked (method, args, &error);
+               mono_error_raise_exception (&error); /* OK to throw, external only with no better option */
+               return rval;
+       }
+}
+
+/*
+ * Execute a standard Main() method (args doesn't contain the
+ * executable name).
+ *
+ * On failure sets @error
+ */
+int
+mono_runtime_exec_main_checked (MonoMethod *method, MonoArray *args, MonoError *error)
+{
+       mono_error_init (error);
+       prepare_thread_to_exec_main (mono_object_domain (args), method);
+       return do_exec_main_checked (method, args, error);
+}
+
+/*
+ * Execute a standard Main() method (args doesn't contain the
+ * executable name).
+ *
+ * On failure sets @error if Main couldn't be executed, or @exc if it threw an exception.
+ */
+int
+mono_runtime_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc, MonoError *error)
+{
+       mono_error_init (error);
+       prepare_thread_to_exec_main (mono_object_domain (args), method);
+       return do_try_exec_main (method, args, exc, error);
+}
+
+
+
 /** invoke_array_extract_argument:
  * @params: array of arguments to the method.
  * @i: the index of the argument to extract.
index 0a5a7b0bc0ff9897b4bff67481917ca192369a5b..24f7284e8e29fe365e3933622a98983951e09830 100644 (file)
@@ -279,10 +279,12 @@ mono_runtime_exec_managed_code (MonoDomain *domain,
                                MonoMainThreadFunc main_func,
                                void* main_args);
 
+MONO_RT_EXTERNAL_ONLY
 MONO_API int
 mono_runtime_run_main      (MonoMethod *method, int argc, char* argv[], 
                             MonoObject **exc);
 
+MONO_RT_EXTERNAL_ONLY
 MONO_API int
 mono_runtime_exec_main     (MonoMethod *method, MonoArray *args,
                             MonoObject **exc);
index 1a7b15b6f55ad75f301e44531a82e8714d3c280d..9835ccc6f08b2245239554a00de8408dd45c412f 100644 (file)
@@ -1026,10 +1026,14 @@ mono_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[
        }
        
        if (mono_llvm_only) {
-               MonoObject *exc;
+               MonoObject *exc = NULL;
                int res;
 
-               res = mono_runtime_run_main (method, argc, argv, &exc);
+               res = mono_runtime_try_run_main (method, argc, argv, &exc, &error);
+               if (exc == NULL && !is_ok (&error))
+                       exc = (MonoObject*) mono_error_convert_to_exception (&error);
+               else
+                       mono_error_cleanup (&error);
                if (exc) {
                        mono_unhandled_exception (exc);
                        mono_invoke_unhandled_exception_hook (exc);
@@ -1037,7 +1041,9 @@ mono_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[
                }
                return res;
        } else {
-               return mono_runtime_run_main (method, argc, argv, NULL);
+               int res = mono_runtime_run_main_checked (method, argc, argv, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
+               return res;
        }
 }