summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDana Keeler <dkeeler@mozilla.com>2021-07-14 14:42:24 +0000
committerMoonchild <moonchild@palemoon.org>2021-07-14 14:42:24 +0000
commit361743b222f7558c102c1321947e2f6d2ed2508e (patch)
tree6677e4195141d8d139563f1e08167da2bb66a8a0
parentce2938d27451e37dfb3f6709055b1d02faf40ab9 (diff)
downloaduxp-361743b222f7558c102c1321947e2f6d2ed2508e.tar.gz
[NSPR] Lock access to PRCallOnceType members in PR_CallOnce* for thread safety.
Cherry-picked upstream fix from 4.31
-rw-r--r--nsprpub/pr/src/misc/prinit.c46
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)