From 15f198378a61a31505bffbac7e798f605c901c4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Laval?= Date: Fri, 17 Mar 2017 14:17:37 -0400 Subject: [PATCH] [monodroid] On Windows, look for side-by-side libmonosgen (#496) Fixes: 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 +++++++++++++++++++++++++++ src/monodroid/monodroid.props | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/monodroid/jni/monodroid-glue.c b/src/monodroid/jni/monodroid-glue.c index e612bdf1cac..7180b6d23b8 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]; + HMODULE module = NULL; + + if (libmonoandroid_directory_path != NULL) + return libmonoandroid_directory_path; + + DWORD flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT; + if (!GetModuleHandleExW (flags, (void*)&libmonoandroid_directory_path, &module)) + return NULL; + + GetModuleFileNameW (module, module_path, sizeof (module_path) / sizeof (module_path[0])); + PathRemoveFileSpecW (module_path); + libmonoandroid_directory_path = utf16_to_utf8 (module_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 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