From bebf9d4f0a546a5b965e969886432cb3b04b4a00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Laval?= Date: Wed, 15 Mar 2017 16:11:00 -0400 Subject: [PATCH 1/6] [jni] On Windows, look for side-by-side libmonosgen. Fix #53163 Context: https://bugzilla.xamarin.com/show_bug.cgi?id=53163 A user uncovered an issue using the Xamarin.Forms previewer where libmonosgen failed to load correctly on Windows. The root cause was that the already loaded libmono-android was incompatible with the version of mono being loaded (different bridge versions) causing a forced runtime shutdown with the error message: Invalid bridge callback version. Expected 4 but got 5 After investigating, it turns out the user had an old version of Xamarin installed via MSI (for VS2015) on his machine and was trying to use the newer Xamarin embedded in VS2017 via the Willow distribution mechanism which places binaries such as libmonosgen in a separate directory structure. Thus the problem was that, while libmono-android itself was loaded correctly from that separate path, the code was then trying to fetch libmonosgen from the global system path (now completely obsolete) causing the bridge version mismatch. With this patch, the code will now try first to get libmonosgen from the same directory libmono-android was loaded from which should cover the Willow case. --- src/monodroid/jni/monodroid-glue.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/monodroid/jni/monodroid-glue.c b/src/monodroid/jni/monodroid-glue.c index b0e3390ddaf..7b929e94c9c 100644 --- a/src/monodroid/jni/monodroid-glue.c +++ b/src/monodroid/jni/monodroid-glue.c @@ -45,6 +45,7 @@ #include #include #include +#include #endif #include @@ -535,6 +536,28 @@ get_xamarin_android_msbuild_path (void) return msbuild_folder_path; } +static char *libmonoandroid_directory_path = NULL; + +// Returns the directory in which this library was loaded from +static char* +get_libmonoandroid_directory_path () +{ + wchar_t module_path[MAX_PATH]; + char *converted_path = NULL; + HMODULE module = NULL; + + if (libmonoandroid_directory_path != NULL) + return libmonoandroid_directory_path; + + if (!GetModuleHandleEx (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (LPCSTR)&libmonoandroid_directory_path, &module)) + return NULL; + GetModuleFileNameW (module, module_path, sizeof (module_path)); + converted_path = utf16_to_utf8 (module_path); + libmonoandroid_directory_path = dirname (converted_path); + return libmonoandroid_directory_path; +} + static int setenv(const char *name, const char *value, int overwrite) { @@ -656,6 +679,10 @@ get_libmonosgen_path () return libmonoso; free (libmonoso); +#ifdef WINDOWS + TRY_LIBMONOSGEN (get_libmonoandroid_directory_path ()) +#endif + TRY_LIBMONOSGEN (SYSTEM_LIB_PATH) #ifdef RELEASE From 14d852ae65c537b7182eaad09a65e82796dc7191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Laval?= Date: Thu, 16 Mar 2017 11:06:04 -0400 Subject: [PATCH 2/6] [jni] Fix method call parameters alignment --- src/monodroid/jni/monodroid-glue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/monodroid/jni/monodroid-glue.c b/src/monodroid/jni/monodroid-glue.c index 7b929e94c9c..b8dda9a5a85 100644 --- a/src/monodroid/jni/monodroid-glue.c +++ b/src/monodroid/jni/monodroid-glue.c @@ -549,8 +549,8 @@ get_libmonoandroid_directory_path () if (libmonoandroid_directory_path != NULL) return libmonoandroid_directory_path; - if (!GetModuleHandleEx (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, - (LPCSTR)&libmonoandroid_directory_path, &module)) + DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT; + if (!GetModuleHandleEx (flags, (LPCSTR)&libmonoandroid_directory_path, &module)) return NULL; GetModuleFileNameW (module, module_path, sizeof (module_path)); converted_path = utf16_to_utf8 (module_path); From b92256fc4ccd4fa82c92bf8dc3fcdfefb297b952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Laval?= Date: Thu, 16 Mar 2017 11:09:27 -0400 Subject: [PATCH 3/6] [jni] Pass correct size for GetModuleFileNameW --- src/monodroid/jni/monodroid-glue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/monodroid/jni/monodroid-glue.c b/src/monodroid/jni/monodroid-glue.c index b8dda9a5a85..e87e6a3fad7 100644 --- a/src/monodroid/jni/monodroid-glue.c +++ b/src/monodroid/jni/monodroid-glue.c @@ -552,7 +552,8 @@ get_libmonoandroid_directory_path () DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT; if (!GetModuleHandleEx (flags, (LPCSTR)&libmonoandroid_directory_path, &module)) return NULL; - GetModuleFileNameW (module, module_path, sizeof (module_path)); + + GetModuleFileNameW (module, module_path, sizeof (module_path) / sizeof (module_path[0])); converted_path = utf16_to_utf8 (module_path); libmonoandroid_directory_path = dirname (converted_path); return libmonoandroid_directory_path; From 3ec06320b64efaf9e0159e3583cfbc4bd8c80147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Laval?= Date: Thu, 16 Mar 2017 11:12:44 -0400 Subject: [PATCH 4/6] [jni] Cast to `void*` instead of `LPCSTR` to make it clear the string type doesn't matter --- src/monodroid/jni/monodroid-glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/monodroid/jni/monodroid-glue.c b/src/monodroid/jni/monodroid-glue.c index e87e6a3fad7..97857498f94 100644 --- a/src/monodroid/jni/monodroid-glue.c +++ b/src/monodroid/jni/monodroid-glue.c @@ -550,7 +550,7 @@ get_libmonoandroid_directory_path () return libmonoandroid_directory_path; DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT; - if (!GetModuleHandleEx (flags, (LPCSTR)&libmonoandroid_directory_path, &module)) + if (!GetModuleHandleEx (flags, (void*)&libmonoandroid_directory_path, &module)) return NULL; GetModuleFileNameW (module, module_path, sizeof (module_path) / sizeof (module_path[0])); From 6f19c289b8461813b59d1d66c409d7fd2b274129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Laval?= Date: Thu, 16 Mar 2017 15:29:11 -0400 Subject: [PATCH 5/6] [jni] GetModuleHandleEx -> GetModuleHandleExW --- src/monodroid/jni/monodroid-glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/monodroid/jni/monodroid-glue.c b/src/monodroid/jni/monodroid-glue.c index 97857498f94..422d8bf2107 100644 --- a/src/monodroid/jni/monodroid-glue.c +++ b/src/monodroid/jni/monodroid-glue.c @@ -550,7 +550,7 @@ get_libmonoandroid_directory_path () return libmonoandroid_directory_path; DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT; - if (!GetModuleHandleEx (flags, (void*)&libmonoandroid_directory_path, &module)) + if (!GetModuleHandleExW (flags, (void*)&libmonoandroid_directory_path, &module)) return NULL; GetModuleFileNameW (module, module_path, sizeof (module_path) / sizeof (module_path[0])); From f1e91fcea1089850f543c8cfc95dfd5c4e5c3597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Laval?= Date: Fri, 17 Mar 2017 11:47:11 -0400 Subject: [PATCH 6/6] [jni] Use PathRemoveFileSpec instead of dirname to compute directory of module --- src/monodroid/jni/monodroid-glue.c | 7 +++---- src/monodroid/monodroid.props | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/monodroid/jni/monodroid-glue.c b/src/monodroid/jni/monodroid-glue.c index 422d8bf2107..57183905b96 100644 --- a/src/monodroid/jni/monodroid-glue.c +++ b/src/monodroid/jni/monodroid-glue.c @@ -45,7 +45,7 @@ #include #include #include -#include +#include #endif #include @@ -543,7 +543,6 @@ static char* get_libmonoandroid_directory_path () { wchar_t module_path[MAX_PATH]; - char *converted_path = NULL; HMODULE module = NULL; if (libmonoandroid_directory_path != NULL) @@ -554,8 +553,8 @@ get_libmonoandroid_directory_path () return NULL; GetModuleFileNameW (module, module_path, sizeof (module_path) / sizeof (module_path[0])); - converted_path = utf16_to_utf8 (module_path); - libmonoandroid_directory_path = dirname (converted_path); + PathRemoveFileSpecW (module_path); + libmonoandroid_directory_path = utf16_to_utf8 (module_path); return libmonoandroid_directory_path; } diff --git a/src/monodroid/monodroid.props b/src/monodroid/monodroid.props index 177c103081b..d2ee096fc28 100644 --- a/src/monodroid/monodroid.props +++ b/src/monodroid/monodroid.props @@ -7,7 +7,7 @@ <_HostUnixCFlags>$(_CommonCFlags) -Wa,--noexecstack <_HostUnixLdFlags>-Wall -lstdc++ -lz -shared -fpic <_HostCommonWinCFlags>$(_CommonCFlags) -DWINDOWS -DNTDDI_VERSION=NTDDI_VISTA -D_WIN32_WINNT=_WIN32_WINNT_VISTA -fomit-frame-pointer - <_HostCommonWinLdFlags>-Wall -lstdc++ -lz -shared -fpic -ldl -lmman -pthread -lwsock32 -lole32 -luuid + <_HostCommonWinLdFlags>-Wall -lstdc++ -lz -shared -fpic -ldl -lmman -pthread -lwsock32 -lole32 -luuid -lshlwapi <_UnixAdditionalSourceFiles>$(MonoSourceFullPath)\support\nl.c jni\debug.c jni\monodroid-networkinfo.c jni\xamarin_getifaddrs.c <_LinuxFlatPakBuild Condition="Exists('/.flatpak-info')" >-DLINUX_FLATPAK