Backed out changeset 67d13c5fcf84 (bug 956899)

This commit is contained in:
Sebastian Hengst 2016-05-28 01:39:00 +02:00
Родитель 92e03fa97f
Коммит 166e149908
1 изменённых файлов: 78 добавлений и 40 удалений

Просмотреть файл

@ -79,9 +79,6 @@
#include "shell/jsoptparse.h"
#include "shell/jsshell.h"
#include "shell/OSObject.h"
#include "threading/ConditionVariable.h"
#include "threading/LockGuard.h"
#include "threading/Mutex.h"
#include "vm/ArgumentsObject.h"
#include "vm/Compression.h"
#include "vm/Debugger.h"
@ -170,12 +167,12 @@ struct ShellRuntime
/*
* Watchdog thread state.
*/
Mutex watchdogLock;
ConditionVariable watchdogWakeup;
PRLock* watchdogLock;
PRCondVar* watchdogWakeup;
PRThread* watchdogThread;
Maybe<TimeStamp> watchdogTimeout;
ConditionVariable sleepWakeup;
PRCondVar* sleepWakeup;
int exitCode;
bool quitting;
@ -219,6 +216,9 @@ mozilla::Atomic<bool> jsCacheOpened(false);
static bool
SetTimeoutValue(JSContext* cx, double t);
static bool
InitWatchdog(JSRuntime* rt);
static void
KillWatchdog(JSRuntime *rt);
@ -315,7 +315,10 @@ ShellRuntime::ShellRuntime(JSRuntime* rt)
#ifdef SPIDERMONKEY_PROMISE
promiseRejectionTrackerCallback(rt, NullValue()),
#endif // SPIDERMONKEY_PROMISE
watchdogLock(nullptr),
watchdogWakeup(nullptr),
watchdogThread(nullptr),
sleepWakeup(nullptr),
exitCode(0),
quitting(false),
gotError(false)
@ -2933,6 +2936,12 @@ WorkerMain(void* arg)
JS_InitDestroyPrincipalsCallback(rt, ShellPrincipals::destroy);
SetWorkerRuntimeOptions(rt);
if (!InitWatchdog(rt)) {
JS_DestroyRuntime(rt);
js_delete(input);
return;
}
JSContext* cx = NewContext(rt);
if (!cx) {
JS_DestroyRuntime(rt);
@ -3092,43 +3101,63 @@ Sleep_fn(JSContext* cx, unsigned argc, Value* vp)
return false;
}
}
{
LockGuard<Mutex> guard(sr->watchdogLock);
TimeStamp toWakeup = TimeStamp::Now() + duration;
for (;;) {
sr->sleepWakeup.wait_for(guard, duration);
if (sr->serviceInterrupt)
break;
auto now = TimeStamp::Now();
if (now >= toWakeup)
break;
duration = toWakeup - now;
}
PR_Lock(sr->watchdogLock);
TimeStamp toWakeup = TimeStamp::Now() + duration;
for (;;) {
PR_WaitCondVar(sr->sleepWakeup, DurationToPRInterval(duration));
if (sr->serviceInterrupt)
break;
auto now = TimeStamp::Now();
if (now >= toWakeup)
break;
duration = toWakeup - now;
}
PR_Unlock(sr->watchdogLock);
args.rval().setUndefined();
return !sr->serviceInterrupt;
}
static bool
InitWatchdog(JSRuntime* rt)
{
ShellRuntime* sr = GetShellRuntime(rt);
MOZ_ASSERT(!sr->watchdogThread);
sr->watchdogLock = PR_NewLock();
if (sr->watchdogLock) {
sr->watchdogWakeup = PR_NewCondVar(sr->watchdogLock);
if (sr->watchdogWakeup) {
sr->sleepWakeup = PR_NewCondVar(sr->watchdogLock);
if (sr->sleepWakeup)
return true;
PR_DestroyCondVar(sr->watchdogWakeup);
}
PR_DestroyLock(sr->watchdogLock);
}
return false;
}
static void
KillWatchdog(JSRuntime* rt)
{
ShellRuntime* sr = GetShellRuntime(rt);
PRThread* thread;
{
LockGuard<Mutex> guard(sr->watchdogLock);
thread = sr->watchdogThread;
if (thread) {
/*
* The watchdog thread is running, tell it to terminate waking it up
* if necessary.
*/
sr->watchdogThread = nullptr;
sr->watchdogWakeup.notify_one();
}
PR_Lock(sr->watchdogLock);
thread = sr->watchdogThread;
if (thread) {
/*
* The watchdog thread is running, tell it to terminate waking it up
* if necessary.
*/
sr->watchdogThread = nullptr;
PR_NotifyCondVar(sr->watchdogWakeup);
}
PR_Unlock(sr->watchdogLock);
if (thread)
PR_JoinThread(thread);
PR_DestroyCondVar(sr->sleepWakeup);
PR_DestroyCondVar(sr->watchdogWakeup);
PR_DestroyLock(sr->watchdogLock);
}
static void
@ -3139,7 +3168,7 @@ WatchdogMain(void* arg)
JSRuntime* rt = (JSRuntime*) arg;
ShellRuntime* sr = GetShellRuntime(rt);
LockGuard<Mutex> guard(sr->watchdogLock);
PR_Lock(sr->watchdogLock);
while (sr->watchdogThread) {
auto now = TimeStamp::Now();
if (sr->watchdogTimeout.isSome() && now >= sr->watchdogTimeout.value()) {
@ -3148,13 +3177,12 @@ WatchdogMain(void* arg)
* outside the lock.
*/
sr->watchdogTimeout = Nothing();
{
UnlockGuard<Mutex> unlock(guard);
CancelExecution(rt);
}
PR_Unlock(sr->watchdogLock);
CancelExecution(rt);
PR_Lock(sr->watchdogLock);
/* Wake up any threads doing sleep. */
sr->sleepWakeup.notify_all();
PR_NotifyAllCondVar(sr->sleepWakeup);
} else {
if (sr->watchdogTimeout.isSome()) {
/*
@ -3167,9 +3195,12 @@ WatchdogMain(void* arg)
TimeDuration sleepDuration = sr->watchdogTimeout.isSome()
? TimeDuration::FromSeconds(0.1)
: TimeDuration::Forever();
sr->watchdogWakeup.wait_for(guard, sleepDuration);
mozilla::DebugOnly<PRStatus> status =
PR_WaitCondVar(sr->watchdogWakeup, DurationToPRInterval(sleepDuration));
MOZ_ASSERT(status == PR_SUCCESS);
}
}
PR_Unlock(sr->watchdogLock);
}
static bool
@ -3178,14 +3209,15 @@ ScheduleWatchdog(JSRuntime* rt, double t)
ShellRuntime* sr = GetShellRuntime(rt);
if (t <= 0) {
LockGuard<Mutex> guard(sr->watchdogLock);
PR_Lock(sr->watchdogLock);
sr->watchdogTimeout = Nothing();
PR_Unlock(sr->watchdogLock);
return true;
}
auto interval = TimeDuration::FromSeconds(t);
auto timeout = TimeStamp::Now() + interval;
LockGuard<Mutex> guard(sr->watchdogLock);
PR_Lock(sr->watchdogLock);
if (!sr->watchdogThread) {
MOZ_ASSERT(sr->watchdogTimeout.isNothing());
sr->watchdogThread = PR_CreateThread(PR_USER_THREAD,
@ -3195,12 +3227,15 @@ ScheduleWatchdog(JSRuntime* rt, double t)
PR_GLOBAL_THREAD,
PR_JOINABLE_THREAD,
0);
if (!sr->watchdogThread)
if (!sr->watchdogThread) {
PR_Unlock(sr->watchdogLock);
return false;
}
} else if (sr->watchdogTimeout.isNothing() || timeout < sr->watchdogTimeout.value()) {
sr->watchdogWakeup.notify_one();
PR_NotifyCondVar(sr->watchdogWakeup);
}
sr->watchdogTimeout = Some(timeout);
PR_Unlock(sr->watchdogLock);
return true;
}
@ -7395,6 +7430,9 @@ main(int argc, char** argv, char** envp)
if (!offThreadState.init())
return 1;
if (!InitWatchdog(rt))
return 1;
cx = NewContext(rt);
if (!cx)
return 1;