You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
3.6 KiB
95 lines
3.6 KiB
# HG changeset patch |
|
# User Daiki Ueno <dueno@redhat.com> |
|
# Date 1521731296 -3600 |
|
# Thu Mar 22 16:08:16 2018 +0100 |
|
# Node ID 6ae3ab8a1e7b4161f3f8eee90db7a745acced408 |
|
# Parent dedf5290c679153e5b3555ba9c711fe62323c156 |
|
Bug 1447628, devslot: avoid deadlock when re-inserting a token, r=rrelyea |
|
|
|
diff --git a/lib/dev/devslot.c b/lib/dev/devslot.c |
|
--- a/lib/dev/devslot.c |
|
+++ b/lib/dev/devslot.c |
|
@@ -96,10 +96,16 @@ nssSlot_ResetDelay( |
|
} |
|
|
|
static PRBool |
|
-within_token_delay_period(const NSSSlot *slot) |
|
+token_status_checked(const NSSSlot *slot) |
|
{ |
|
PRIntervalTime time; |
|
int lastPingState = slot->lastTokenPingState; |
|
+ /* When called from the same thread, that means |
|
+ * nssSlot_IsTokenPresent() is called recursively through |
|
+ * nssSlot_Refresh(). Return immediately in that case. */ |
|
+ if (slot->isPresentThread == PR_GetCurrentThread()) { |
|
+ return PR_TRUE; |
|
+ } |
|
/* Set the delay time for checking the token presence */ |
|
if (s_token_delay_time == 0) { |
|
s_token_delay_time = PR_SecondsToInterval(NSSSLOT_TOKEN_DELAY_TIME); |
|
@@ -130,7 +136,7 @@ nssSlot_IsTokenPresent( |
|
|
|
/* avoid repeated calls to check token status within set interval */ |
|
PZ_Lock(slot->isPresentLock); |
|
- if (within_token_delay_period(slot)) { |
|
+ if (token_status_checked(slot)) { |
|
CK_FLAGS ckFlags = slot->ckFlags; |
|
PZ_Unlock(slot->isPresentLock); |
|
return ((ckFlags & CKF_TOKEN_PRESENT) != 0); |
|
@@ -146,12 +152,12 @@ nssSlot_IsTokenPresent( |
|
|
|
/* set up condition so only one thread is active in this part of the code at a time */ |
|
PZ_Lock(slot->isPresentLock); |
|
- while (slot->inIsPresent) { |
|
+ while (slot->isPresentThread) { |
|
PR_WaitCondVar(slot->isPresentCondition, 0); |
|
} |
|
/* if we were one of multiple threads here, the first thread will have |
|
* given us the answer, no need to make more queries of the token. */ |
|
- if (within_token_delay_period(slot)) { |
|
+ if (token_status_checked(slot)) { |
|
CK_FLAGS ckFlags = slot->ckFlags; |
|
PZ_Unlock(slot->isPresentLock); |
|
return ((ckFlags & CKF_TOKEN_PRESENT) != 0); |
|
@@ -159,7 +165,7 @@ nssSlot_IsTokenPresent( |
|
/* this is the winning thread, block all others until we've determined |
|
* if the token is present and that it needs initialization. */ |
|
slot->lastTokenPingState = nssSlotLastPingState_Update; |
|
- slot->inIsPresent = PR_TRUE; |
|
+ slot->isPresentThread = PR_GetCurrentThread(); |
|
|
|
PZ_Unlock(slot->isPresentLock); |
|
|
|
@@ -257,7 +263,7 @@ done: |
|
slot->lastTokenPingTime = PR_IntervalNow(); |
|
slot->lastTokenPingState = nssSlotLastPingState_Valid; |
|
} |
|
- slot->inIsPresent = PR_FALSE; |
|
+ slot->isPresentThread = NULL; |
|
PR_NotifyAllCondVar(slot->isPresentCondition); |
|
PZ_Unlock(slot->isPresentLock); |
|
return isPresent; |
|
diff --git a/lib/dev/devt.h b/lib/dev/devt.h |
|
--- a/lib/dev/devt.h |
|
+++ b/lib/dev/devt.h |
|
@@ -92,7 +92,7 @@ struct NSSSlotStr { |
|
PK11SlotInfo *pk11slot; |
|
PZLock *isPresentLock; |
|
PRCondVar *isPresentCondition; |
|
- PRBool inIsPresent; |
|
+ PRThread *isPresentThread; |
|
}; |
|
|
|
struct nssSessionStr { |
|
diff --git a/lib/pk11wrap/dev3hack.c b/lib/pk11wrap/dev3hack.c |
|
--- a/lib/pk11wrap/dev3hack.c |
|
+++ b/lib/pk11wrap/dev3hack.c |
|
@@ -122,7 +122,7 @@ nssSlot_CreateFromPK11SlotInfo(NSSTrustD |
|
rvSlot->lock = (nss3slot->isThreadSafe) ? NULL : nss3slot->sessionLock; |
|
rvSlot->isPresentLock = PZ_NewLock(nssiLockOther); |
|
rvSlot->isPresentCondition = PR_NewCondVar(rvSlot->isPresentLock); |
|
- rvSlot->inIsPresent = PR_FALSE; |
|
+ rvSlot->isPresentThread = NULL; |
|
rvSlot->lastTokenPingState = nssSlotLastPingState_Reset; |
|
return rvSlot; |
|
}
|
|
|