diff --git a/dlls/mscoree/corruntimehost.c b/dlls/mscoree/corruntimehost.c index 3c26340a82a..02547532730 100644 --- a/dlls/mscoree/corruntimehost.c +++ b/dlls/mscoree/corruntimehost.c @@ -44,7 +44,7 @@ struct RuntimeHost const struct ICorRuntimeHostVtbl *lpVtbl; const struct ICLRRuntimeHostVtbl *lpCLRHostVtbl; const CLRRuntimeInfo *version; - const loaded_mono *mono; + loaded_mono *mono; struct list domains; MonoDomain *default_domain; CRITICAL_SECTION lock; @@ -91,6 +91,8 @@ static HRESULT RuntimeHost_AddDomain(RuntimeHost *This, MonoDomain **result) goto end; } + This->mono->is_started = TRUE; + list_add_tail(&This->domains, &entry->entry); MSCOREE_LockModule(); @@ -131,7 +133,6 @@ static void RuntimeHost_DeleteDomain(RuntimeHost *This, MonoDomain *domain) { if (entry->domain == domain) { - This->mono->mono_jit_cleanup(domain); list_remove(&entry->entry); if (This->default_domain == domain) This->default_domain = NULL; @@ -711,11 +712,13 @@ __int32 WINAPI _CorExeMain(void) HeapFree(GetProcessHeap(), 0, argv); + unload_all_runtimes(); + return exit_code; } HRESULT RuntimeHost_Construct(const CLRRuntimeInfo *runtime_version, - const loaded_mono *loaded_mono, RuntimeHost** result) + loaded_mono *loaded_mono, RuntimeHost** result) { RuntimeHost *This; @@ -786,7 +789,6 @@ HRESULT RuntimeHost_Destroy(RuntimeHost *This) LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->domains, struct DomainEntry, entry) { - This->mono->mono_jit_cleanup(cursor->domain); list_remove(&cursor->entry); HeapFree(GetProcessHeap(), 0, cursor); } diff --git a/dlls/mscoree/metahost.c b/dlls/mscoree/metahost.c index 2cafcb8f881..72215f03eb4 100644 --- a/dlls/mscoree/metahost.c +++ b/dlls/mscoree/metahost.c @@ -76,6 +76,8 @@ static BOOL find_mono_dll(LPCWSTR path, LPWSTR dll_path, int abi_version); static MonoAssembly* mono_assembly_search_hook_fn(MonoAssemblyName *aname, char **assemblies_path, void *user_data); +static void mono_shutdown_callback_fn(MonoProfiler *prof); + static void set_environment(LPCWSTR bin_path) { WCHAR path_env[MAX_PATH]; @@ -91,6 +93,10 @@ static void set_environment(LPCWSTR bin_path) SetEnvironmentVariableW(pathW, path_env); } +static void CDECL do_nothing(void) +{ +} + static HRESULT load_mono(CLRRuntimeInfo *This, loaded_mono **result) { static const WCHAR bin[] = {'\\','b','i','n',0}; @@ -111,6 +117,13 @@ static HRESULT load_mono(CLRRuntimeInfo *This, loaded_mono **result) *result = &loaded_monos[This->mono_abi_version-1]; + if ((*result)->is_shutdown) + { + ERR("Cannot load Mono after it has been shut down."); + *result = NULL; + return E_FAIL; + } + if (!(*result)->mono_handle) { strcpyW(mono_bin_path, This->mono_path); @@ -146,16 +159,17 @@ static HRESULT load_mono(CLRRuntimeInfo *This, loaded_mono **result) LOAD_MONO_FUNCTION(mono_class_get_method_from_name); LOAD_MONO_FUNCTION(mono_domain_assembly_open); LOAD_MONO_FUNCTION(mono_install_assembly_preload_hook); - LOAD_MONO_FUNCTION(mono_jit_cleanup); LOAD_MONO_FUNCTION(mono_jit_exec); LOAD_MONO_FUNCTION(mono_jit_init); LOAD_MONO_FUNCTION(mono_jit_set_trace_options); LOAD_MONO_FUNCTION(mono_object_get_domain); LOAD_MONO_FUNCTION(mono_object_new); LOAD_MONO_FUNCTION(mono_object_unbox); + LOAD_MONO_FUNCTION(mono_profiler_install); LOAD_MONO_FUNCTION(mono_reflection_type_from_name); LOAD_MONO_FUNCTION(mono_runtime_invoke); LOAD_MONO_FUNCTION(mono_runtime_object_init); + LOAD_MONO_FUNCTION(mono_runtime_quit); LOAD_MONO_FUNCTION(mono_set_dirs); LOAD_MONO_FUNCTION(mono_stringify_assembly_name); @@ -175,6 +189,22 @@ static HRESULT load_mono(CLRRuntimeInfo *This, loaded_mono **result) #undef LOAD_MONO_FUNCTION +#define LOAD_OPT_VOID_MONO_FUNCTION(x) do { \ + (*result)->x = (void*)GetProcAddress((*result)->mono_handle, #x); \ + if (!(*result)->x) { \ + (*result)->x = do_nothing; \ + } \ +} while (0); + + LOAD_OPT_VOID_MONO_FUNCTION(mono_runtime_set_shutting_down); + LOAD_OPT_VOID_MONO_FUNCTION(mono_thread_pool_cleanup); + LOAD_OPT_VOID_MONO_FUNCTION(mono_thread_suspend_all_other_threads); + LOAD_OPT_VOID_MONO_FUNCTION(mono_threads_set_shutting_down); + +#undef LOAD_OPT_VOID_MONO_FUNCTION + + (*result)->mono_profiler_install((MonoProfiler*)*result, mono_shutdown_callback_fn); + (*result)->mono_set_dirs(mono_lib_path_a, mono_etc_path_a); (*result)->mono_config_parse(NULL); @@ -200,6 +230,13 @@ fail: return E_FAIL; } +static void mono_shutdown_callback_fn(MonoProfiler *prof) +{ + loaded_mono *mono = (loaded_mono*)prof; + + mono->is_shutdown = TRUE; +} + static HRESULT CLRRuntimeInfo_GetRuntimeHost(CLRRuntimeInfo *This, RuntimeHost **result) { HRESULT hr = S_OK; @@ -230,11 +267,40 @@ void unload_all_runtimes(void) { int i; + for (i=0; imono_handle && mono->is_started && !mono->is_shutdown) + { + /* Copied from Mono's ves_icall_System_Environment_Exit */ + mono->mono_threads_set_shutting_down(); + mono->mono_runtime_set_shutting_down(); + mono->mono_thread_pool_cleanup(); + mono->mono_thread_suspend_all_other_threads(); + mono->mono_runtime_quit(); + } + } + for (i=0; imono_handle && mono->is_started && !mono->is_shutdown) + { + ERR("Process exited with a Mono runtime loaded.\n"); + return; + } + } +} + static HRESULT WINAPI CLRRuntimeInfo_QueryInterface(ICLRRuntimeInfo* iface, REFIID riid, void **ppvObject) diff --git a/dlls/mscoree/mscoree_main.c b/dlls/mscoree/mscoree_main.c index a3e1ceccaf1..6901f7a6b75 100644 --- a/dlls/mscoree/mscoree_main.c +++ b/dlls/mscoree/mscoree_main.c @@ -124,7 +124,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) DisableThreadLibraryCalls(hinstDLL); break; case DLL_PROCESS_DETACH: - unload_all_runtimes(); + expect_no_runtimes(); break; } return TRUE; @@ -154,7 +154,8 @@ __int32 WINAPI _CorExeMain2(PBYTE ptrMemory, DWORD cntMemory, LPWSTR imageName, void WINAPI CorExitProcess(int exitCode) { - FIXME("(%x) stub\n", exitCode); + TRACE("(%x)\n", exitCode); + unload_all_runtimes(); ExitProcess(exitCode); } diff --git a/dlls/mscoree/mscoree_private.h b/dlls/mscoree/mscoree_private.h index 222b3caf8ba..16ae5d3825b 100644 --- a/dlls/mscoree/mscoree_private.h +++ b/dlls/mscoree/mscoree_private.h @@ -85,6 +85,7 @@ typedef struct _MonoImage MonoImage; typedef struct _MonoClass MonoClass; typedef struct _MonoObject MonoObject; typedef struct _MonoMethod MonoMethod; +typedef struct _MonoProfiler MonoProfiler; typedef enum { MONO_IMAGE_OK, @@ -95,11 +96,16 @@ typedef enum { typedef MonoAssembly* (*MonoAssemblyPreLoadFunc)(MonoAssemblyName *aname, char **assemblies_path, void *user_data); +typedef void (*MonoProfileFunc)(MonoProfiler *prof); + typedef struct loaded_mono { HMODULE mono_handle; HMODULE glib_handle; + BOOL is_started; + BOOL is_shutdown; + MonoImage* (CDECL *mono_assembly_get_image)(MonoAssembly *assembly); MonoAssembly* (CDECL *mono_assembly_open)(const char *filename, MonoImageOpenStatus *status); MonoClass* (CDECL *mono_class_from_mono_type)(MonoType *type); @@ -109,25 +115,32 @@ typedef struct loaded_mono MonoAssembly* (CDECL *mono_domain_assembly_open) (MonoDomain *domain, const char *name); void (CDECL *mono_free)(void *); void (CDECL *mono_install_assembly_preload_hook)(MonoAssemblyPreLoadFunc func, void *user_data); - void (CDECL *mono_jit_cleanup)(MonoDomain *domain); int (CDECL *mono_jit_exec)(MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]); MonoDomain* (CDECL *mono_jit_init)(const char *file); int (CDECL *mono_jit_set_trace_options)(const char* options); MonoDomain* (CDECL *mono_object_get_domain)(MonoObject *obj); MonoObject* (CDECL *mono_object_new)(MonoDomain *domain, MonoClass *klass); void* (CDECL *mono_object_unbox)(MonoObject *obj); + void (CDECL *mono_profiler_install)(MonoProfiler *prof, MonoProfileFunc shutdown_callback); MonoType* (CDECL *mono_reflection_type_from_name)(char *name, MonoImage *image); MonoObject* (CDECL *mono_runtime_invoke)(MonoMethod *method, void *obj, void **params, MonoObject **exc); void (CDECL *mono_runtime_object_init)(MonoObject *this_obj); + void (CDECL *mono_runtime_quit)(void); + void (CDECL *mono_runtime_set_shutting_down)(void); void (CDECL *mono_set_dirs)(const char *assembly_dir, const char *config_dir); char* (CDECL *mono_stringify_assembly_name)(MonoAssemblyName *aname); + void (CDECL *mono_thread_pool_cleanup)(void); + void (CDECL *mono_thread_suspend_all_other_threads)(void); + void (CDECL *mono_threads_set_shutting_down)(void); } loaded_mono; /* loaded runtime interfaces */ extern void unload_all_runtimes(void); +extern void expect_no_runtimes(void); + extern HRESULT RuntimeHost_Construct(const CLRRuntimeInfo *runtime_version, - const loaded_mono *loaded_mono, RuntimeHost** result); + loaded_mono *loaded_mono, RuntimeHost** result); extern HRESULT RuntimeHost_GetInterface(RuntimeHost *This, REFCLSID clsid, REFIID riid, void **ppv);