Blame SOURCES/nss-fix-deadlock-squash.patch

1b6f66
diff --git a/lib/pki/tdcache.c b/lib/pki/tdcache.c
1b6f66
--- a/lib/pki/tdcache.c
1b6f66
+++ b/lib/pki/tdcache.c
1b6f66
@@ -379,23 +379,29 @@ nssTrustDomain_UnlockCertCache (
1b6f66
 
1b6f66
 struct token_cert_dtor {
1b6f66
     NSSToken *token;
1b6f66
     nssTDCertificateCache *cache;
1b6f66
     NSSCertificate **certs;
1b6f66
     PRUint32 numCerts, arrSize;
1b6f66
 };
1b6f66
 
1b6f66
+static void cert_iter(const void *k, void *v, void *a)
1b6f66
+{
1b6f66
+    nssList *certList = (nssList *)a;
1b6f66
+    NSSCertificate *c = (NSSCertificate *)k;
1b6f66
+    nssList_Add(certList, nssCertificate_AddRef(c));
1b6f66
+}
1b6f66
+
1b6f66
 static void 
1b6f66
-remove_token_certs(const void *k, void *v, void *a)
1b6f66
+remove_token_certs(NSSCertificate *c, struct token_cert_dtor *dtor) 
1b6f66
 {
1b6f66
-    NSSCertificate *c = (NSSCertificate *)k;
1b6f66
     nssPKIObject *object = &c->object;
1b6f66
-    struct token_cert_dtor *dtor = a;
1b6f66
     PRUint32 i;
1b6f66
+
1b6f66
     nssPKIObject_AddRef(object);
1b6f66
     nssPKIObject_Lock(object);
1b6f66
     for (i=0; i<object->numInstances; i++) {
1b6f66
 	if (object->instances[i]->token == dtor->token) {
1b6f66
 	    nssCryptokiObject_Destroy(object->instances[i]);
1b6f66
 	    object->instances[i] = object->instances[object->numInstances-1];
1b6f66
 	    object->instances[object->numInstances-1] = NULL;
1b6f66
 	    object->numInstances--;
1b6f66
@@ -422,45 +428,83 @@ NSS_IMPLEMENT PRStatus
1b6f66
 nssTrustDomain_RemoveTokenCertsFromCache (
1b6f66
   NSSTrustDomain *td,
1b6f66
   NSSToken *token
1b6f66
 )
1b6f66
 {
1b6f66
     NSSCertificate **certs;
1b6f66
     PRUint32 i, arrSize = 10;
1b6f66
     struct token_cert_dtor dtor;
1b6f66
+    nssList *certList;
1b6f66
+    PRStatus nspr_rv = PR_FAILURE;
1b6f66
+    nssListIterator *iter;
1b6f66
+    NSSCertificate *c;
1b6f66
+
1b6f66
     certs = nss_ZNEWARRAY(NULL, NSSCertificate *, arrSize);
1b6f66
     if (!certs) {
1b6f66
 	return PR_FAILURE;
1b6f66
     }
1b6f66
     dtor.cache = td->cache;
1b6f66
     dtor.token = token;
1b6f66
     dtor.certs = certs;
1b6f66
     dtor.numCerts = 0;
1b6f66
     dtor.arrSize = arrSize;
1b6f66
+
1b6f66
+    certList = nssList_Create(NULL, PR_FALSE);
1b6f66
+    if (!certList) {
1b6f66
+	goto loser;
1b6f66
+    }
1b6f66
+    /* fetch the list of certs in the cache */
1b6f66
     PZ_Lock(td->cache->lock);
1b6f66
-    nssHash_Iterate(td->cache->issuerAndSN, remove_token_certs, &dtor);
1b6f66
+    nssHash_Iterate(td->cache->issuerAndSN, cert_iter, (void *)certList);
1b6f66
+    PZ_Unlock(td->cache->lock);
1b6f66
+
1b6f66
+    /* find the certs that match this token without olding the td cache lock */
1b6f66
+    iter=nssList_CreateIterator(certList);
1b6f66
+    if (!iter) {
1b6f66
+	goto loser;
1b6f66
+    }
1b6f66
+    for (c  = (NSSCertificate *)nssListIterator_Start(iter);
1b6f66
+	 c != (NSSCertificate *)NULL;
1b6f66
+	 c  = (NSSCertificate *)nssListIterator_Next(iter)) {
1b6f66
+	remove_token_certs( c, &dtor);
1b6f66
+    }
1b6f66
+    nssListIterator_Finish(iter);
1b6f66
+    nssListIterator_Destroy(iter);
1b6f66
+    nssList_Destroy(certList);
1b6f66
+    certList = NULL;
1b6f66
+
1b6f66
+    /* now remove theose certs attached to this token */
1b6f66
+    PZ_Lock(td->cache->lock);
1b6f66
     for (i=0; i
1b6f66
 	if (dtor.certs[i]->object.numInstances == 0) {
1b6f66
 	    nssTrustDomain_RemoveCertFromCacheLOCKED(td, dtor.certs[i]);
1b6f66
 	    dtor.certs[i] = NULL;  /* skip this cert in the second for loop */
1b6f66
 	} else {
1b6f66
 	    /* make sure it doesn't disappear on us before we finish */
1b6f66
 	    nssCertificate_AddRef(dtor.certs[i]);
1b6f66
 	}
1b6f66
     }
1b6f66
     PZ_Unlock(td->cache->lock);
1b6f66
+
1b6f66
+    /* clean up */
1b6f66
     for (i=0; i
1b6f66
 	if (dtor.certs[i]) {
1b6f66
 	    STAN_ForceCERTCertificateUpdate(dtor.certs[i]);
1b6f66
 	    nssCertificate_Destroy(dtor.certs[i]);
1b6f66
 	}
1b6f66
     }
1b6f66
+
1b6f66
+    nspr_rv = PR_SUCCESS;
1b6f66
+loser:
1b6f66
+    if (certList) {
1b6f66
+	nssList_Destroy(certList);
1b6f66
+    }
1b6f66
     nss_ZFreeIf(dtor.certs);
1b6f66
-    return PR_SUCCESS;
1b6f66
+    return nspr_rv;
1b6f66
 }
1b6f66
 
1b6f66
 NSS_IMPLEMENT PRStatus
1b6f66
 nssTrustDomain_UpdateCachedTokenCerts (
1b6f66
   NSSTrustDomain *td,
1b6f66
   NSSToken *token
1b6f66
 )
1b6f66
 {
1b6f66
@@ -1073,23 +1117,16 @@ nssTrustDomain_GetCertByDERFromCache (
1b6f66
 #endif
1b6f66
     rvCert = nssTrustDomain_GetCertForIssuerAndSNFromCache(td, 
1b6f66
                                                            &issuer, &serial);
1b6f66
     PORT_Free(issuer.data);
1b6f66
     PORT_Free(serial.data);
1b6f66
     return rvCert;
1b6f66
 }
1b6f66
 
1b6f66
-static void cert_iter(const void *k, void *v, void *a)
1b6f66
-{
1b6f66
-    nssList *certList = (nssList *)a;
1b6f66
-    NSSCertificate *c = (NSSCertificate *)k;
1b6f66
-    nssList_Add(certList, nssCertificate_AddRef(c));
1b6f66
-}
1b6f66
-
1b6f66
 NSS_EXTERN NSSCertificate **
1b6f66
 nssTrustDomain_GetCertsFromCache (
1b6f66
   NSSTrustDomain *td,
1b6f66
   nssList *certListOpt
1b6f66
 )
1b6f66
 {
1b6f66
     NSSCertificate **rvArray = NULL;
1b6f66
     nssList *certList;