diff options
author | Dana Keeler <dkeeler@mozilla.com> | 2021-07-14 14:42:24 +0000 |
---|---|---|
committer | Moonchild <moonchild@palemoon.org> | 2021-07-14 14:42:24 +0000 |
commit | 361743b222f7558c102c1321947e2f6d2ed2508e (patch) | |
tree | 6677e4195141d8d139563f1e08167da2bb66a8a0 /nsprpub | |
parent | ce2938d27451e37dfb3f6709055b1d02faf40ab9 (diff) | |
download | uxp-361743b222f7558c102c1321947e2f6d2ed2508e.tar.gz |
[NSPR] Lock access to PRCallOnceType members in PR_CallOnce* for thread safety.
Cherry-picked upstream fix from 4.31
Diffstat (limited to 'nsprpub')
-rw-r--r-- | nsprpub/pr/src/misc/prinit.c | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/nsprpub/pr/src/misc/prinit.c b/nsprpub/pr/src/misc/prinit.c index 5ac99fe588..a952ad6554 100644 --- a/nsprpub/pr/src/misc/prinit.c +++ b/nsprpub/pr/src/misc/prinit.c @@ -771,10 +771,15 @@ PR_IMPLEMENT(PRStatus) PR_CallOnce( _PR_ImplicitInitialization(); } - if (!once->initialized) { + 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) { - once->status = (*func)(); + status = (*func)(); PR_Lock(mod_init.ml); + once->status = status; once->initialized = 1; PR_NotifyAllCondVar(mod_init.cv); PR_Unlock(mod_init.ml); @@ -783,14 +788,18 @@ PR_IMPLEMENT(PRStatus) PR_CallOnce( while (!once->initialized) { PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT); } + status = once->status; PR_Unlock(mod_init.ml); + if (PR_SUCCESS != status) { + PR_SetError(PR_CALL_ONCE_ERROR, 0); + } } - } else { - if (PR_SUCCESS != once->status) { - PR_SetError(PR_CALL_ONCE_ERROR, 0); - } + return status; + } + if (PR_SUCCESS != status) { + PR_SetError(PR_CALL_ONCE_ERROR, 0); } - return once->status; + return status; } PR_IMPLEMENT(PRStatus) PR_CallOnceWithArg( @@ -802,10 +811,15 @@ PR_IMPLEMENT(PRStatus) PR_CallOnceWithArg( _PR_ImplicitInitialization(); } - if (!once->initialized) { + 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) { - once->status = (*func)(arg); + status = (*func)(arg); PR_Lock(mod_init.ml); + once->status = status; once->initialized = 1; PR_NotifyAllCondVar(mod_init.cv); PR_Unlock(mod_init.ml); @@ -814,14 +828,18 @@ PR_IMPLEMENT(PRStatus) PR_CallOnceWithArg( while (!once->initialized) { PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT); } + status = once->status; PR_Unlock(mod_init.ml); + if (PR_SUCCESS != status) { + PR_SetError(PR_CALL_ONCE_ERROR, 0); + } } - } else { - if (PR_SUCCESS != once->status) { - PR_SetError(PR_CALL_ONCE_ERROR, 0); - } + return status; + } + if (PR_SUCCESS != status) { + PR_SetError(PR_CALL_ONCE_ERROR, 0); } - return once->status; + return status; } PRBool _PR_Obsolete(const char *obsolete, const char *preferred) |