From fa1d656af4c4ea81ca04c7f0117e421855327a28 Mon Sep 17 00:00:00 2001 From: Ignacio Etcheverry Date: Sun, 18 Mar 2018 23:02:06 +0100 Subject: [PATCH] Mono: Runtime main args and assembly search fixes - Setup runtime main args during initialization. This must be done manually by embedders who do not call mono_runtime_run_main. Fixes NullReferenceException in System.Environment. - Continue to search the assembly in the rest of the search locations if loading it from one of them failed. --- modules/mono/mono_gd/gd_mono.cpp | 31 +++++++++++++++++++++-- modules/mono/mono_gd/gd_mono_assembly.cpp | 26 +++++++++---------- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index 1ebef045617..0646580eaae 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -74,7 +74,31 @@ void gdmono_MonoPrintCallback(const char *string, mono_bool is_stdout) { GDMono *GDMono::singleton = NULL; +namespace { + +void setup_runtime_main_args() { + CharString execpath = OS::get_singleton()->get_executable_path().utf8(); + + List cmdline_args = OS::get_singleton()->get_cmdline_args(); + + List cmdline_args_utf8; + Vector main_args; + main_args.resize(cmdline_args.size() + 1); + + main_args[0] = execpath.ptrw(); + + int i = 1; + for (List::Element *E = cmdline_args.front(); E; E = E->next()) { + CharString &stored = cmdline_args_utf8.push_back(E->get().utf8())->get(); + main_args[i] = stored.ptrw(); + i++; + } + + mono_runtime_set_main_args(main_args.size(), main_args.ptrw()); +} + #ifdef DEBUG_ENABLED + static bool _wait_for_debugger_msecs(uint32_t p_msecs) { do { @@ -96,9 +120,7 @@ static bool _wait_for_debugger_msecs(uint32_t p_msecs) { return mono_is_debugger_attached(); } -#endif -#ifdef DEBUG_ENABLED void gdmono_debug_init() { mono_debug_init(MONO_DEBUG_FORMAT_MONO); @@ -125,8 +147,11 @@ void gdmono_debug_init() { }; mono_jit_parse_options(2, (char **)options); } + #endif +} // namespace + void GDMono::initialize() { ERR_FAIL_NULL(Engine::get_singleton()); @@ -179,6 +204,8 @@ void GDMono::initialize() { GDMonoUtils::set_main_thread(GDMonoUtils::get_current_thread()); + setup_runtime_main_args(); // Required for System.Environment.GetCommandLineArgs + runtime_initialized = true; OS::get_singleton()->print("Mono: Runtime initialized\n"); diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index 2ce1b0a9df4..5982d2da18a 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -85,19 +85,22 @@ MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_d path = search_dir.plus_file(name); if (FileAccess::exists(path)) { res = _load_assembly_from(name.get_basename(), path, refonly); - break; + if (res != NULL) + break; } } else { path = search_dir.plus_file(name + ".dll"); if (FileAccess::exists(path)) { res = _load_assembly_from(name, path, refonly); - break; + if (res != NULL) + break; } path = search_dir.plus_file(name + ".exe"); if (FileAccess::exists(path)) { res = _load_assembly_from(name, path, refonly); - break; + if (res != NULL) + break; } } } @@ -151,19 +154,15 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse path = search_dir.plus_file(name); if (FileAccess::exists(path)) { res = _load_assembly_from(name.get_basename(), path, refonly); - break; + if (res != NULL) + break; } } else { path = search_dir.plus_file(name + ".dll"); if (FileAccess::exists(path)) { res = _load_assembly_from(name, path, refonly); - break; - } - - path = search_dir.plus_file(name + ".exe"); - if (FileAccess::exists(path)) { - res = _load_assembly_from(name, path, refonly); - break; + if (res != NULL) + break; } } } @@ -212,14 +211,15 @@ Error GDMonoAssembly::load(bool p_refonly) { String image_filename(path); - MonoImageOpenStatus status; + MonoImageOpenStatus status = MONO_IMAGE_OK; image = mono_image_open_from_data_with_name( (char *)&data[0], data.size(), true, &status, refonly, image_filename.utf8().get_data()); - ERR_FAIL_COND_V(status != MONO_IMAGE_OK || image == NULL, ERR_FILE_CANT_OPEN); + ERR_FAIL_COND_V(status != MONO_IMAGE_OK, ERR_FILE_CANT_OPEN); + ERR_FAIL_NULL_V(image, ERR_FILE_CANT_OPEN); #ifdef DEBUG_ENABLED String pdb_path(path + ".pdb");