Bug 1243248 - Fix shell-only workerThreads races. r=jonco

--HG--
extra : rebase_source : 1cf8f7b9cc28c56a848df9e170e8d79daf1922e3
This commit is contained in:
Jan de Mooij 2016-01-27 13:38:02 +01:00
parent a7cc7fa9ec
commit 1c3e9791a8

View File

@ -2829,7 +2829,21 @@ WorkerMain(void* arg)
js_delete(input);
}
Vector<PRThread*, 0, SystemAllocPolicy> workerThreads;
// Workers can spawn other workers, so we need a lock to access workerThreads.
static PRLock* workerThreadsLock = nullptr;
static Vector<PRThread*, 0, SystemAllocPolicy> workerThreads;
class MOZ_RAII AutoLockWorkerThreads
{
public:
AutoLockWorkerThreads() {
MOZ_ASSERT(workerThreadsLock);
PR_Lock(workerThreadsLock);
}
~AutoLockWorkerThreads() {
PR_Unlock(workerThreadsLock);
}
};
static bool
EvalInWorker(JSContext* cx, unsigned argc, Value* vp)
@ -2848,6 +2862,14 @@ EvalInWorker(JSContext* cx, unsigned argc, Value* vp)
if (!args[0].toString()->ensureLinear(cx))
return false;
if (!workerThreadsLock) {
workerThreadsLock = PR_NewLock();
if (!workerThreadsLock) {
ReportOutOfMemory(cx);
return false;
}
}
JSLinearString* str = &args[0].toString()->asLinear();
char16_t* chars = (char16_t*) js_malloc(str->length() * sizeof(char16_t));
@ -2872,6 +2894,7 @@ EvalInWorker(JSContext* cx, unsigned argc, Value* vp)
return false;
}
AutoLockWorkerThreads alwt;
if (!workerThreads.append(thread)) {
ReportOutOfMemory(cx);
PR_JoinThread(thread);
@ -3068,6 +3091,34 @@ ScheduleWatchdog(JSRuntime* rt, double t)
return true;
}
static void
KillWorkerThreads()
{
MOZ_ASSERT_IF(!CanUseExtraThreads(), workerThreads.empty());
if (!workerThreadsLock) {
MOZ_ASSERT(workerThreads.empty());
return;
}
while (true) {
// We need to leave the AutoLockWorkerThreads scope before we call
// PR_JoinThread, to avoid deadlocks when AutoLockWorkerThreads is
// used by the worker thread.
PRThread* thread;
{
AutoLockWorkerThreads alwt;
if (workerThreads.empty())
break;
thread = workerThreads.popCopy();
}
PR_JoinThread(thread);
}
PR_DestroyLock(workerThreadsLock);
workerThreadsLock = nullptr;
}
static void
CancelExecution(JSRuntime* rt)
{
@ -7010,9 +7061,7 @@ main(int argc, char** argv, char** envp)
KillWatchdog(rt);
MOZ_ASSERT_IF(!CanUseExtraThreads(), workerThreads.empty());
for (size_t i = 0; i < workerThreads.length(); i++)
PR_JoinThread(workerThreads[i]);
KillWorkerThreads();
DestructSharedArrayBufferMailbox();