Bug 1389967 In MinGW, work around a pointer to a function thunk disappearing when we unload nssckbi r?franziskus draft
authorTom Ritter <tom@mozilla.com>
Tue, 08 May 2018 11:51:57 -0500
changeset 795402 3e465b60d2165145edf9b5a83330845ad6110bc7
parent 795401 04ece02dd826bd2ed111a13a8da7415a9e92c877
push id109956
push userbmo:tom@mozilla.com
push dateTue, 15 May 2018 19:02:54 +0000
reviewersfranziskus
bugs1389967
milestone60.0
Bug 1389967 In MinGW, work around a pointer to a function thunk disappearing when we unload nssckbi r?franziskus MozReview-Commit-ID: 8Y09kTFUVIQ
nsprpub/pr/include/prthread.h
nsprpub/pr/src/threads/prtpd.c
security/nss/lib/base/error.c
old mode 100644
new mode 100755
--- a/nsprpub/pr/include/prthread.h
+++ b/nsprpub/pr/include/prthread.h
@@ -187,16 +187,33 @@ NSPR_API(const char *) PR_GetThreadName(
 ** allowed.
 */
 typedef void (PR_CALLBACK *PRThreadPrivateDTOR)(void *priv);
 
 NSPR_API(PRStatus) PR_NewThreadPrivateIndex(
     PRUintn *newIndex, PRThreadPrivateDTOR destructor);
 
 /*
+** This function is redundant. It performs the same thing as the above
+** function when called like so:
+**   PR_NewThreadPrivateIndex(newIndex, PR_Free);
+**
+** However, this function passes a function pointer that is within its
+** own module, 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.
+*/
+NSPR_API(PRStatus) PR_NewThreadPrivateIndexWithPR_Free(
+    PRUintn *newIndex);
+
+/*
 ** Define some per-thread-private data.
 **     "tpdIndex" is an index into the per-thread private data table
 **     "priv" is the per-thread-private data 
 **
 ** If the per-thread private data table has a previously registered
 ** destructor function and a non-NULL per-thread-private data value,
 ** the destructor function is invoked.
 **
--- a/nsprpub/pr/src/threads/prtpd.c
+++ b/nsprpub/pr/src/threads/prtpd.c
@@ -116,16 +116,22 @@ PR_IMPLEMENT(PRStatus) PR_NewThreadPriva
         _pr_tpd_destructors[index] = dtor;  /* record destructor @index */
         *newIndex = (PRUintn)index;  /* copy into client's location */
         rv = PR_SUCCESS;  /* that's okay */
     }
 
     return rv;
 }
 
+PR_IMPLEMENT(PRStatus) PR_NewThreadPrivateIndexWithPR_Free(
+    PRUintn *newIndex)
+{
+    return PR_NewThreadPrivateIndex(newIndex, PR_Free);
+}
+
 /*
 ** Define some per-thread-private data.
 **     "index" is an index into the per-thread private data table
 **     "priv" is the per-thread-private data 
 **
 ** If the per-thread private data table has a previously registered
 ** destructor function and a non-NULL per-thread-private data value,
 ** the destructor function is invoked.
--- a/security/nss/lib/base/error.c
+++ b/security/nss/lib/base/error.c
@@ -60,17 +60,17 @@ static const PRCallOnceType error_call_a
 /*
  * error_once_function
  *
  * This is the once-called callback.
  */
 static PRStatus
 error_once_function(void)
 {
-    return PR_NewThreadPrivateIndex(&error_stack_index, PR_Free);
+    return PR_NewThreadPrivateIndexWithPR_Free(&error_stack_index);
 }
 
 /*
  * 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.