[NSPR] Lock access to PRCallOnceType members in PR_CallOnce* for thread safety.

Cherry-picked upstream fix from 4.31
This commit is contained in:
Dana Keeler 2021-07-14 14:42:24 +00:00 • committed by roytam1
commit bfac131dc2

View file

@ -771,10 +771,15 @@ PR_IMPLEMENT(PRStatus) PR_CallOnce(
_PR_ImplicitInitialization(); _PR_ImplicitInitialization();
} }
if (!once->initialized) {
if (PR_ATOMIC_SET(&once->inProgress, 1) == 0) {
once->status = (*func)();
PR_Lock(mod_init.ml); PR_Lock(mod_init.ml);
PRIntn initialized = once->initialized;
PRStatus status = once->status;
PR_Unlock(mod_init.ml);
if (!initialized) {
if (PR_ATOMIC_SET(&once->inProgress, 1) == 0) {
status = (*func)();
PR_Lock(mod_init.ml);
once->status = status;
once->initialized = 1; once->initialized = 1;
PR_NotifyAllCondVar(mod_init.cv); PR_NotifyAllCondVar(mod_init.cv);
PR_Unlock(mod_init.ml); PR_Unlock(mod_init.ml);
@ -783,14 +788,18 @@ PR_IMPLEMENT(PRStatus) PR_CallOnce(
while (!once->initialized) { while (!once->initialized) {
PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT); PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT);
} }
status = once->status;
PR_Unlock(mod_init.ml); PR_Unlock(mod_init.ml);
} if (PR_SUCCESS != status) {
} else {
if (PR_SUCCESS != once->status) {
PR_SetError(PR_CALL_ONCE_ERROR, 0); PR_SetError(PR_CALL_ONCE_ERROR, 0);
} }
} }
return once->status; return status;
}
if (PR_SUCCESS != status) {
PR_SetError(PR_CALL_ONCE_ERROR, 0);
}
return status;
} }
PR_IMPLEMENT(PRStatus) PR_CallOnceWithArg( PR_IMPLEMENT(PRStatus) PR_CallOnceWithArg(
@ -802,10 +811,15 @@ PR_IMPLEMENT(PRStatus) PR_CallOnceWithArg(
_PR_ImplicitInitialization(); _PR_ImplicitInitialization();
} }
if (!once->initialized) {
if (PR_ATOMIC_SET(&once->inProgress, 1) == 0) {
once->status = (*func)(arg);
PR_Lock(mod_init.ml); PR_Lock(mod_init.ml);
PRIntn initialized = once->initialized;
PRStatus status = once->status;
PR_Unlock(mod_init.ml);
if (!initialized) {
if (PR_ATOMIC_SET(&once->inProgress, 1) == 0) {
status = (*func)(arg);
PR_Lock(mod_init.ml);
once->status = status;
once->initialized = 1; once->initialized = 1;
PR_NotifyAllCondVar(mod_init.cv); PR_NotifyAllCondVar(mod_init.cv);
PR_Unlock(mod_init.ml); PR_Unlock(mod_init.ml);
@ -814,14 +828,18 @@ PR_IMPLEMENT(PRStatus) PR_CallOnceWithArg(
while (!once->initialized) { while (!once->initialized) {
PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT); PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT);
} }
status = once->status;
PR_Unlock(mod_init.ml); PR_Unlock(mod_init.ml);
} if (PR_SUCCESS != status) {
} else {
if (PR_SUCCESS != once->status) {
PR_SetError(PR_CALL_ONCE_ERROR, 0); PR_SetError(PR_CALL_ONCE_ERROR, 0);
} }
} }
return once->status; return status;
}
if (PR_SUCCESS != status) {
PR_SetError(PR_CALL_ONCE_ERROR, 0);
}
return status;
} }
PRBool _PR_Obsolete(const char *obsolete, const char *preferred) PRBool _PR_Obsolete(const char *obsolete, const char *preferred)