[Mono-devel-list] embedding mono with threads

eric lindvall eric at 5stops.com
Mon Jul 21 11:49:54 EDT 2003


who do i need to talk to, or what do i need to do to find out how to fix
this?

i've sent messages to this list as well as submitted a bug for this.

i've done what i can to figure it out on my own, and haven't been able to
do that successfully.

e.


On Wed, 09 Jul 2003, eric lindvall wrote:

> I've had all sorts of troubles embedding mono in a world of pthreads.
> 
> The biggest problems i've found are that:
> 
> - I can't seem to run mono_jit_init() from a thread other than the "main
>   thread" (see oxide-3)
> - odd things start to happen when i use pthread_create() and then use
>   mono_thread_attach() (see oxide-2)
> - if mono_runtime_exec_managed_code() isn't used, nothing works right --
>   I'm not quite sure how much and what I'm supposed to do with that call
>   though.. once I call it, can I run everything else in a different
>   thread?
> 
> I've found other smaller odd issues, like when i try to use
> mono_runtime_invoke() on a MonoObject that is a TransparentProxy, it seems
> to run in the default app domain, instead of the app domain of the object
> that is being proxied.. but that's a story for another email. (using
> mono_object_get_virtual_method() seemed to give me the correct object, but
> i am not sure if it's the right answer).
> 
> I have included both a tarball of my source as well as included the main
> .c files for reference.
> 
> I also included a managed parity of the unmanaged code: oxide-bin.exe.
> 
> The differences between the three unmaraged versions:
> 
> oxide-1: nothing is using pthreads
> 
>          result:
> 	   everything works.
> 
> oxide-2: initialization happens in the main thread, but the "request"
>          happens in a pthread
> 
>          result:
> 	   Unhandled Exception: System.NullReferenceException: A null value was found where an object instance was required 
> 	   in [0x000e6] (at /home/eric/src/mono/mcs/class/System.Web/System.Web.Hosting/ApplicationHost.cs:62) 00 System.Web.Hosting.ApplicationHost:CreateApplicationHost (System.Type,string,string) 
> 	   in [0x0000c] (at /home/eric/src/oxide_test/managed/OxideApplicationHost.cs:46) 00 Fivestops.Oxide.OxideApplicationHost:CreateApplicationHost (string,string)
> 
> oxide-3: initialization attempts to happen in a pthread (and segfaults)
> 
>          result:
> 	   Segmentation fault
> 
> e.
> 
> 


> 
> #include <sys/select.h>
> 
> #include <mono/jit/jit.h>
> #include <mono/metadata/environment.h>
> #include <mono/metadata/debug-helpers.h>
> #include <mono/metadata/mono-debug.h>
> #include <mono/metadata/threads.h>
> 
> #define DOCROOT "/home/eric/xsp/test"
> #define DLL_LOCATION "oxide.dll"
> 
> static MonoDomain *g_domain;
> static MonoAssembly *g_assembly;
> 
> static MonoObject *g_appHost;
> 
> void oxideHandler (void *p);
> 
> static char *
> GetVariable (char *key)
> {
>     if (strcmp (key, "ntrans-base") == 0)
>     {
>         return (DOCROOT);
>     }
>     else if (strcmp (key, "HasInittedMono") == 0)
>     {
>         return (NULL); // nope
>     }
>     else if (strcmp (key, "uri") == 0)
>     {
>         return ("index.aspx");
>     }
>     else if (strcmp (key, "query") == 0)
>     {
>         return ("");
>     }
> 
>     return (NULL);
> }
> 
> static void
> oxideSetupMono (gpointer userData)
> {
>     char *assemblyLocation = DLL_LOCATION;
> 
>     g_assembly = mono_domain_assembly_open (g_domain, assemblyLocation);
> 
>     if (g_assembly == NULL)
>     {
>         printf ("OXIDE: could not load assembly: %s\n", assemblyLocation);
> 
>         mono_environment_exitcode_set (-1);
>     }
>     else
>     {
>         printf ("OXIDE: loaded assembly: %s\n", assemblyLocation);
> 
>         mono_debug_init_2 (g_assembly);
>         g_domain->entry_assembly = g_assembly;
> 
>         mono_environment_exitcode_set (0);
>     }
> }
> 
> void
> oxideInit (void *p)
> {
>     int ret = 0;
> 
>     g_domain = mono_jit_init ("oxide-domain");
> 
>     if (g_domain == NULL)
>     {
>         printf ("OXIDE: could not initialize application domain.\n");
>         
>         return;
>     }
> 
>     mono_debug_init (MONO_DEBUG_FORMAT_MONO);
> 
>     mono_runtime_exec_managed_code (g_domain, oxideSetupMono, NULL);
>     
>     ret = mono_environment_exitcode_get();
> 
>     printf ("OXIDE: exit code: %d\n", ret);
> 
>     if (ret == 0)
>     {
>         printf ("OXIDE: successfully started.\n");
>     }
>     else
>     {
>         mono_jit_cleanup (g_domain);
> 
>         printf ("OXIDE: error, could not start.\n");
>     }
> }
> 
> static MonoObject *
> oxideAppHostSetup (char *virtualDir, char *baseDir)
> {
>     MonoMethodDesc *methodDesc;
>     MonoMethod *method;
>     MonoObject *appHost;
>     gpointer params[2];
> 
>     methodDesc = mono_method_desc_new ("Fivestops.Oxide.OxideApplicationHost:CreateApplicationHost", TRUE);
>     method = mono_method_desc_search_in_image (methodDesc, g_assembly->image);
> 
>     if (virtualDir != NULL && *virtualDir != 0)
>         params[0] = mono_string_new (g_domain, virtualDir);
>     else
>         params[0] = NULL;
> 
>     if (baseDir != NULL && *baseDir != 0)
>         params[1] = mono_string_new (g_domain, baseDir);
>     else
>         params[1] = NULL;
> 
>     appHost = mono_runtime_invoke (method, NULL, params, NULL);
> 
>     return (appHost);
> }
> 
> static MonoObject *
> oxideGetAppHost (char *virtualDir, char *baseDir)
> {
>     if (g_appHost == NULL)
>     {
>         g_appHost = oxideAppHostSetup (virtualDir, baseDir);
>     }
> 
>     return (g_appHost);
> }
> 
> static char *
> oxideGetVirtualDir ()
> {
>     return ("/");
> }
> 
> static char *
> oxideProcessRequest (MonoObject *appHost, char *page, char *query)
> {
>     MonoMethodDesc *methodDesc;
>     MonoMethod *method;
>     MonoString *response;
>     gpointer params[2];
> 
>     methodDesc = mono_method_desc_new ("Fivestops.Oxide.OxideApplicationHost:HandleRequest", TRUE);
>     method = mono_method_desc_search_in_image (methodDesc, g_assembly->image);
>     method = mono_object_get_virtual_method (appHost, method);
> 
>     printf ("OXIDE: HandleRequest: %p\n", method);
> 
>     if (method == NULL)
>     {
>         return ("(error)");
>     }
> 
>     if (page != NULL && *page != 0)
>         params[0] = mono_string_new (g_domain, page);
>     else
>         params[0] = NULL;
> 
>     if (query != NULL && *query != 0)
>         params[1] = mono_string_new (g_domain, query);
>     else
>         params[1] = NULL;
> 
>     response = (MonoString *) mono_runtime_invoke (method, appHost, params, NULL);
> 
>     return (mono_string_to_utf8 (response));
> }
> 
> 
> void
> oxideHandler (void *p)
> {
>     MonoObject *appHost;
>     char *docRoot;
>     char *response;
>     void *hasInitted;
> 
>     docRoot = GetVariable ("ntrans-base");
> 
>     if (docRoot == NULL)
>     {
>         printf ("OXIDE: no docRoot defined\n");
> 
>         return;
>     }
> 
>     hasInitted = GetVariable ("HasInittedMono");
> 
>     if (hasInitted == NULL)
>     {
>         printf ("OXIDE: calling mono_thread_attach (%p)\n", g_domain);
> 
>         mono_thread_attach (g_domain);
>     }
> 
>     // appHost = oxideGetAppHost (oxideGetVirtualDir(), docRoot);
>     appHost = oxideAppHostSetup (oxideGetVirtualDir(), docRoot);
> 
>     response = oxideProcessRequest (appHost, GetVariable ("uri"),
>             GetVariable ("query"));
> 
>     printf ("response = \n%s\n", response);
> }
> 
> int
> main (int argc, char **argv)
> {
>     oxideInit (NULL);
> 
>     oxideHandler (NULL);
> 
>     return (0);
> }

> 
> #include <sys/select.h>
> 
> #include <mono/jit/jit.h>
> #include <mono/metadata/environment.h>
> #include <mono/metadata/debug-helpers.h>
> #include <mono/metadata/mono-debug.h>
> #include <mono/metadata/threads.h>
> 
> #define DOCROOT "/home/eric/xsp/test"
> #define DLL_LOCATION "oxide.dll"
> 
> static MonoDomain *g_domain;
> static MonoAssembly *g_assembly;
> 
> static MonoObject *g_appHost;
> 
> void oxideHandler (void *p);
> 
> static char *
> GetVariable (char *key)
> {
>     if (strcmp (key, "ntrans-base") == 0)
>     {
>         return (DOCROOT);
>     }
>     else if (strcmp (key, "HasInittedMono") == 0)
>     {
>         return (NULL); // nope
>     }
>     else if (strcmp (key, "uri") == 0)
>     {
>         return ("index.aspx");
>     }
>     else if (strcmp (key, "query") == 0)
>     {
>         return ("");
>     }
> 
>     return (NULL);
> }
> 
> static void
> oxideSetupMono (gpointer userData)
> {
>     char *assemblyLocation = DLL_LOCATION;
> 
>     g_assembly = mono_domain_assembly_open (g_domain, assemblyLocation);
> 
>     if (g_assembly == NULL)
>     {
>         printf ("OXIDE: could not load assembly: %s\n", assemblyLocation);
> 
>         mono_environment_exitcode_set (-1);
>     }
>     else
>     {
>         printf ("OXIDE: loaded assembly: %s\n", assemblyLocation);
> 
>         mono_debug_init_2 (g_assembly);
>         g_domain->entry_assembly = g_assembly;
> 
>         mono_environment_exitcode_set (0);
>     }
> }
> 
> void
> oxideInit (void *p)
> {
>     int ret = 0;
> 
>     g_domain = mono_jit_init ("oxide-domain");
> 
>     if (g_domain == NULL)
>     {
>         printf ("OXIDE: could not initialize application domain.\n");
>         
>         return;
>     }
> 
>     mono_debug_init (MONO_DEBUG_FORMAT_MONO);
> 
>     mono_runtime_exec_managed_code (g_domain, oxideSetupMono, NULL);
>     
>     ret = mono_environment_exitcode_get();
> 
>     printf ("OXIDE: exit code: %d\n", ret);
> 
>     if (ret == 0)
>     {
>         printf ("OXIDE: successfully started.\n");
>     }
>     else
>     {
>         mono_jit_cleanup (g_domain);
> 
>         printf ("OXIDE: error, could not start.\n");
>     }
> }
> 
> static MonoObject *
> oxideAppHostSetup (char *virtualDir, char *baseDir)
> {
>     MonoMethodDesc *methodDesc;
>     MonoMethod *method;
>     MonoObject *appHost;
>     gpointer params[2];
> 
>     methodDesc = mono_method_desc_new ("Fivestops.Oxide.OxideApplicationHost:CreateApplicationHost", TRUE);
>     method = mono_method_desc_search_in_image (methodDesc, g_assembly->image);
> 
>     if (virtualDir != NULL && *virtualDir != 0)
>         params[0] = mono_string_new (g_domain, virtualDir);
>     else
>         params[0] = NULL;
> 
>     if (baseDir != NULL && *baseDir != 0)
>         params[1] = mono_string_new (g_domain, baseDir);
>     else
>         params[1] = NULL;
> 
>     appHost = mono_runtime_invoke (method, NULL, params, NULL);
> 
>     return (appHost);
> }
> 
> static MonoObject *
> oxideGetAppHost (char *virtualDir, char *baseDir)
> {
>     if (g_appHost == NULL)
>     {
>         g_appHost = oxideAppHostSetup (virtualDir, baseDir);
>     }
> 
>     return (g_appHost);
> }
> 
> static char *
> oxideGetVirtualDir ()
> {
>     return ("/");
> }
> 
> static char *
> oxideProcessRequest (MonoObject *appHost, char *page, char *query)
> {
>     MonoMethodDesc *methodDesc;
>     MonoMethod *method;
>     MonoString *response;
>     gpointer params[2];
> 
>     methodDesc = mono_method_desc_new ("Fivestops.Oxide.OxideApplicationHost:HandleRequest", TRUE);
>     method = mono_method_desc_search_in_image (methodDesc, g_assembly->image);
>     method = mono_object_get_virtual_method (appHost, method);
> 
>     printf ("OXIDE: HandleRequest: %p\n", method);
> 
>     if (method == NULL)
>     {
>         return ("(error)");
>     }
> 
>     if (page != NULL && *page != 0)
>         params[0] = mono_string_new (g_domain, page);
>     else
>         params[0] = NULL;
> 
>     if (query != NULL && *query != 0)
>         params[1] = mono_string_new (g_domain, query);
>     else
>         params[1] = NULL;
> 
>     response = (MonoString *) mono_runtime_invoke (method, appHost, params, NULL);
> 
>     return (mono_string_to_utf8 (response));
> }
> 
> 
> void
> oxideHandler (void *p)
> {
>     MonoObject *appHost;
>     char *docRoot;
>     char *response;
>     void *hasInitted;
> 
>     docRoot = GetVariable ("ntrans-base");
> 
>     if (docRoot == NULL)
>     {
>         printf ("OXIDE: no docRoot defined\n");
> 
>         return;
>     }
> 
>     hasInitted = GetVariable ("HasInittedMono");
> 
>     if (hasInitted == NULL)
>     {
>         printf ("OXIDE: calling mono_thread_attach (%p)\n", g_domain);
> 
>         mono_thread_attach (g_domain);
>     }
> 
>     // appHost = oxideGetAppHost (oxideGetVirtualDir(), docRoot);
>     appHost = oxideAppHostSetup (oxideGetVirtualDir(), docRoot);
> 
>     response = oxideProcessRequest (appHost, GetVariable ("uri"),
>             GetVariable ("query"));
> 
>     printf ("response = \n%s\n", response);
> }
> 
> int
> main (int argc, char **argv)
> {
>     pthread_t thread2;
> 
>     oxideInit (NULL);
> 
>     pthread_create (&thread2, NULL, (void *(*)(void *)) oxideHandler, NULL);
> 
>     pthread_join (thread2, NULL);
> 
>     return (0);
> }

> 
> #include <sys/select.h>
> 
> #include <mono/jit/jit.h>
> #include <mono/metadata/environment.h>
> #include <mono/metadata/debug-helpers.h>
> #include <mono/metadata/mono-debug.h>
> #include <mono/metadata/threads.h>
> 
> #define DOCROOT "/home/eric/xsp/test"
> #define DLL_LOCATION "oxide.dll"
> 
> static MonoDomain *g_domain;
> static MonoAssembly *g_assembly;
> 
> static MonoObject *g_appHost;
> 
> void oxideHandler (void *p);
> 
> static char *
> GetVariable (char *key)
> {
>     if (strcmp (key, "ntrans-base") == 0)
>     {
>         return (DOCROOT);
>     }
>     else if (strcmp (key, "HasInittedMono") == 0)
>     {
>         return (NULL); // nope
>     }
>     else if (strcmp (key, "uri") == 0)
>     {
>         return ("index.aspx");
>     }
>     else if (strcmp (key, "query") == 0)
>     {
>         return ("");
>     }
> 
>     return (NULL);
> }
> 
> static void
> oxideSetupMono (gpointer userData)
> {
>     char *assemblyLocation = DLL_LOCATION;
> 
>     g_assembly = mono_domain_assembly_open (g_domain, assemblyLocation);
> 
>     if (g_assembly == NULL)
>     {
>         printf ("OXIDE: could not load assembly: %s\n", assemblyLocation);
> 
>         mono_environment_exitcode_set (-1);
>     }
>     else
>     {
>         printf ("OXIDE: loaded assembly: %s\n", assemblyLocation);
> 
>         mono_debug_init_2 (g_assembly);
>         g_domain->entry_assembly = g_assembly;
> 
>         mono_environment_exitcode_set (0);
>     }
> }
> 
> void
> oxideInit (void *p)
> {
>     int ret = 0;
> 
>     g_domain = mono_jit_init ("oxide-domain");
> 
>     if (g_domain == NULL)
>     {
>         printf ("OXIDE: could not initialize application domain.\n");
>         
>         return;
>     }
> 
>     mono_debug_init (MONO_DEBUG_FORMAT_MONO);
> 
>     mono_runtime_exec_managed_code (g_domain, oxideSetupMono, NULL);
>     
>     ret = mono_environment_exitcode_get();
> 
>     printf ("OXIDE: exit code: %d\n", ret);
> 
>     if (ret == 0)
>     {
>         printf ("OXIDE: successfully started.\n");
>     }
>     else
>     {
>         mono_jit_cleanup (g_domain);
> 
>         printf ("OXIDE: error, could not start.\n");
>     }
> }
> 
> static MonoObject *
> oxideAppHostSetup (char *virtualDir, char *baseDir)
> {
>     MonoMethodDesc *methodDesc;
>     MonoMethod *method;
>     MonoObject *appHost;
>     gpointer params[2];
> 
>     methodDesc = mono_method_desc_new ("Fivestops.Oxide.OxideApplicationHost:CreateApplicationHost", TRUE);
>     method = mono_method_desc_search_in_image (methodDesc, g_assembly->image);
> 
>     if (virtualDir != NULL && *virtualDir != 0)
>         params[0] = mono_string_new (g_domain, virtualDir);
>     else
>         params[0] = NULL;
> 
>     if (baseDir != NULL && *baseDir != 0)
>         params[1] = mono_string_new (g_domain, baseDir);
>     else
>         params[1] = NULL;
> 
>     appHost = mono_runtime_invoke (method, NULL, params, NULL);
> 
>     return (appHost);
> }
> 
> static MonoObject *
> oxideGetAppHost (char *virtualDir, char *baseDir)
> {
>     if (g_appHost == NULL)
>     {
>         g_appHost = oxideAppHostSetup (virtualDir, baseDir);
>     }
> 
>     return (g_appHost);
> }
> 
> static char *
> oxideGetVirtualDir ()
> {
>     return ("/");
> }
> 
> static char *
> oxideProcessRequest (MonoObject *appHost, char *page, char *query)
> {
>     MonoMethodDesc *methodDesc;
>     MonoMethod *method;
>     MonoString *response;
>     gpointer params[2];
> 
>     methodDesc = mono_method_desc_new ("Fivestops.Oxide.OxideApplicationHost:HandleRequest", TRUE);
>     method = mono_method_desc_search_in_image (methodDesc, g_assembly->image);
>     method = mono_object_get_virtual_method (appHost, method);
> 
>     printf ("OXIDE: HandleRequest: %p\n", method);
> 
>     if (method == NULL)
>     {
>         return ("(error)");
>     }
> 
>     if (page != NULL && *page != 0)
>         params[0] = mono_string_new (g_domain, page);
>     else
>         params[0] = NULL;
> 
>     if (query != NULL && *query != 0)
>         params[1] = mono_string_new (g_domain, query);
>     else
>         params[1] = NULL;
> 
>     response = (MonoString *) mono_runtime_invoke (method, appHost, params, NULL);
> 
>     return (mono_string_to_utf8 (response));
> }
> 
> 
> void
> oxideHandler (void *p)
> {
>     MonoObject *appHost;
>     char *docRoot;
>     char *response;
>     void *hasInitted;
> 
>     docRoot = GetVariable ("ntrans-base");
> 
>     if (docRoot == NULL)
>     {
>         printf ("OXIDE: no docRoot defined\n");
> 
>         return;
>     }
> 
>     hasInitted = GetVariable ("HasInittedMono");
> 
>     if (hasInitted == NULL)
>     {
>         printf ("OXIDE: calling mono_thread_attach (%p)\n", g_domain);
> 
>         mono_thread_attach (g_domain);
>     }
> 
>     // appHost = oxideGetAppHost (oxideGetVirtualDir(), docRoot);
>     appHost = oxideAppHostSetup (oxideGetVirtualDir(), docRoot);
> 
>     response = oxideProcessRequest (appHost, GetVariable ("uri"),
>             GetVariable ("query"));
> 
>     printf ("response = \n%s\n", response);
> }
> 
> int
> main (int argc, char **argv)
> {
>     pthread_t thread1;
>     pthread_t thread2;
> 
>     pthread_create (&thread1, NULL, (void *(*)(void *)) oxideInit, NULL);
> 
>     pthread_join (thread1, NULL);
> 
>     pthread_create (&thread2, NULL, (void *(*)(void *)) oxideHandler, NULL);
> 
>     pthread_join (thread2, NULL);
> 
>     return (0);
> }




More information about the Mono-devel-list mailing list