Bug 1389967 In MinGW, work around a pointer to a function thunk disappearing when we unload nssckbi r=franziskus,dmajor
authorTom Ritter <tom@mozilla.com>
Mon, 21 May 2018 10:40:31 -0500
changeset 14424 783d13e6d3458f291d2b1ae79c7e67bebfa931ed
parent 14423 8051656a6281e778d2e57ed86113401c9cc2875f
child 14425 d23206e032bd35a049b34d9a53224c13bbd68817
push id3141
push userfranziskuskiefer@gmail.com
push dateMon, 23 Jul 2018 06:13:10 +0000
reviewersfranziskus, dmajor
bugs1389967
Bug 1389967 In MinGW, work around a pointer to a function thunk disappearing when we unload nssckbi r=franziskus,dmajor
lib/base/error.c
--- a/lib/base/error.c
+++ b/lib/base/error.c
@@ -10,16 +10,20 @@
  */
 
 #ifndef BASE_H
 #include "base.h"
 #endif              /* BASE_H */
 #include <limits.h> /* for UINT_MAX */
 #include <string.h> /* for memmove */
 
+#if defined(__MINGW32__)
+#include <windows.h>
+#endif
+
 #define NSS_MAX_ERROR_STACK_COUNT 16 /* error codes */
 
 /*
  * The stack itself has a header, and a sequence of integers.
  * The header records the amount of space (as measured in stack
  * slots) already allocated for the stack, and the count of the
  * number of records currently being used.
  */
@@ -60,17 +64,42 @@ static const PRCallOnceType error_call_a
 /*
  * error_once_function
  *
  * This is the once-called callback.
  */
 static PRStatus
 error_once_function(void)
 {
+
+/*
+ * This #ifdef function is redundant. It performs the same thing as the
+ * else case.
+ *
+ * However, the MinGW version looks up the function from nss3's export
+ * table, and on MinGW _that_ behaves differently than passing a
+ * function pointer in a different module because MinGW has
+ * -mnop-fun-dllimport specified, which generates function thunks for
+ * cross-module calls. And when a module (like nssckbi) gets unloaded,
+ * and you try to call into that thunk (which is now missing) you'll
+ * crash. So we do this bit of ugly to avoid that crash. Fortunately
+ * this is the only place we've had to do this.
+ */
+#if defined(__MINGW32__)
+    HMODULE nss3 = GetModuleHandleW(L"nss3");
+    if (nss3) {
+        FARPROC freePtr = GetProcAddress(nss3, "PR_Free");
+        if (freePtr) {
+            return PR_NewThreadPrivateIndex(&error_stack_index, freePtr);
+        }
+    }
     return PR_NewThreadPrivateIndex(&error_stack_index, PR_Free);
+#else
+    return PR_NewThreadPrivateIndex(&error_stack_index, PR_Free);
+#endif
 }
 
 /*
  * error_get_my_stack
  *
  * This routine returns the calling thread's error stack, creating
  * it if necessary.  It may return NULL upon error, which implicitly
  * means that it ran out of memory.