[Mono-devel-list] embedding mono with threads
eric lindvall
eric at 5stops.com
Wed Jul 9 04:17:20 EDT 2003
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.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: oxide_test.tar.gz
Type: application/x-tar-gz
Size: 3037 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/mono-devel-list/attachments/20030709/bfea4da4/attachment.bin
-------------- next part --------------
#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);
}
-------------- next part --------------
#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);
}
-------------- next part --------------
#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