[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