diff --git a/js/src/jsapi-tests/tests.cpp b/js/src/jsapi-tests/tests.cpp index 3ed4bf03ef0..20d84ffcad1 100644 --- a/js/src/jsapi-tests/tests.cpp +++ b/js/src/jsapi-tests/tests.cpp @@ -6,6 +6,10 @@ #include "jsapi-tests/tests.h" +#ifdef XP_WIN +# include "jswin.h" +#endif + #include #include "js/RootingAPI.h" @@ -95,8 +99,20 @@ JSObject * JSAPITest::createGlobal(JSPrincipals* principals) return newGlobal; } +static void PreInit() +{ +#ifdef XP_WIN + // Disable the segfault dialog to avoid hanging when run in automation. + UINT prevMode = SetErrorMode(0); + UINT newMode = SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX; + SetErrorMode(prevMode | newMode); +#endif +} + int main(int argc, char* argv[]) { + PreInit(); + int total = 0; int failures = 0; const char* filter = (argc == 2) ? argv[1] : nullptr; diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index ff71b8c9127..b6d635c2688 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -184,7 +184,7 @@ static FILE* gOutFile = nullptr; static bool reportWarnings = true; static bool compileOnly = false; -static bool fuzzingSafe = false; +static bool gFuzzingSafe = false; #ifdef DEBUG static bool dumpEntrainedVariables = false; @@ -5720,17 +5720,17 @@ NewGlobalObject(JSContext* cx, JS::CompartmentOptions& options, { return nullptr; } - if (!js::DefineTestingFunctions(cx, glob, fuzzingSafe)) + if (!js::DefineTestingFunctions(cx, glob, gFuzzingSafe)) return nullptr; - if (!fuzzingSafe) { + if (!gFuzzingSafe) { if (!JS_DefineFunctionsWithHelp(cx, glob, fuzzing_unsafe_functions)) return nullptr; if (!DefineConsole(cx, glob)) return nullptr; } - if (!DefineOS(cx, glob, fuzzingSafe)) + if (!DefineOS(cx, glob, gFuzzingSafe)) return nullptr; RootedObject performanceObj(cx, JS_NewObject(cx, nullptr)); @@ -6144,10 +6144,8 @@ Shell(JSContext* cx, OptionParser* op, char** envp) JSAutoRequest ar(cx); - if (op->getBoolOption("fuzzing-safe")) - fuzzingSafe = true; - else - fuzzingSafe = (getenv("MOZ_FUZZING_SAFE") && getenv("MOZ_FUZZING_SAFE")[0] != '0'); + gFuzzingSafe = op->getBoolOption("fuzzing-safe") || + (getenv("MOZ_FUZZING_SAFE") && getenv("MOZ_FUZZING_SAFE")[0] != '0'); RootedObject glob(cx); JS::CompartmentOptions options; @@ -6199,11 +6197,14 @@ static void PreInit() { #ifdef XP_WIN - // Disable the segfault dialog. We want to fail the tests immediately - // instead of hanging automation. - UINT prevMode = SetErrorMode(0); - UINT newMode = SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX; - SetErrorMode(prevMode | newMode); + // Disable the segfault dialog. This is used by test harnesses to fail the + // tests immediately instead of hanging automation. + const char* crash_option = getenv("XRE_NO_WINDOWS_CRASH_DIALOG"); + if (crash_option && strncmp(crash_option, "1", 1)) { + UINT prevMode = SetErrorMode(0); + UINT newMode = SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX; + SetErrorMode(prevMode | newMode); + } #endif } @@ -6218,15 +6219,6 @@ main(int argc, char** argv, char** envp) JSRuntime* rt; JSContext* cx; int result; -#ifdef XP_WIN - { - const char* crash_option = getenv("XRE_NO_WINDOWS_CRASH_DIALOG"); - if (crash_option && strncmp(crash_option, "1", 1)) { - DWORD oldmode = SetErrorMode(SEM_NOGPFAULTERRORBOX); - SetErrorMode(oldmode | SEM_NOGPFAULTERRORBOX); - } - } -#endif #ifdef HAVE_SETLOCALE setlocale(LC_ALL, ""); diff --git a/js/src/tests/lib/jittests.py b/js/src/tests/lib/jittests.py index da9507dad0e..7031a206bd7 100755 --- a/js/src/tests/lib/jittests.py +++ b/js/src/tests/lib/jittests.py @@ -377,6 +377,7 @@ def run_test(test, prefix, options): run = run_cmd env = os.environ.copy() + env['XRE_NO_WINDOWS_CRASH_DIALOG'] = '1' if test.tz_pacific: env['TZ'] = 'PST8PDT' diff --git a/js/src/tests/lib/tasks_unix.py b/js/src/tests/lib/tasks_unix.py index 01b27c98684..3f98df16ceb 100644 --- a/js/src/tests/lib/tasks_unix.py +++ b/js/src/tests/lib/tasks_unix.py @@ -18,7 +18,7 @@ class Task(object): self.out = [] self.err = [] -def spawn_test(test, prefix, passthrough=False): +def spawn_test(test, prefix, env, passthrough=False): """Spawn one child, return a task struct.""" if not passthrough: (rout, wout) = os.pipe() @@ -40,7 +40,7 @@ def spawn_test(test, prefix, passthrough=False): os.dup2(werr, 2) cmd = test.get_command(prefix) - os.execvp(cmd[0], cmd) + os.execvpe(cmd[0], cmd, env) def total_seconds(td): """ @@ -191,13 +191,17 @@ def run_all_tests(tests, prefix, results, options): # The set of currently running tests. tasks = [] + # Add any needed environment variables. + env = os.environ.copy() + env['XRE_NO_WINDOWS_CRASH_DIALOG'] = '1' + while len(tests) or len(tasks): while len(tests) and len(tasks) < options.worker_count: test = tests.pop() if not test.enable and not options.run_skipped: yield NullTestOutput(test) else: - tasks.append(spawn_test(test, prefix, options.passthrough)) + tasks.append(spawn_test(test, prefix, env, options.passthrough)) timeout = get_max_wait(tasks, options.timeout) read_input(tasks, timeout) diff --git a/js/src/tests/lib/tasks_win.py b/js/src/tests/lib/tasks_win.py index b121760c546..cc45e043ad0 100644 --- a/js/src/tests/lib/tasks_win.py +++ b/js/src/tests/lib/tasks_win.py @@ -21,6 +21,9 @@ class TaskFinishedMarker: def _do_work(qTasks, qResults, qWatch, prefix, run_skipped, timeout): + env = os.environ.copy() + env['XRE_NO_WINDOWS_CRASH_DIALOG'] = '1' + while True: test = qTasks.get(block=True, timeout=sys.maxint) if test is EndMarker: @@ -37,7 +40,8 @@ def _do_work(qTasks, qResults, qWatch, prefix, run_skipped, timeout): tStart = datetime.now() proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + stderr=subprocess.PIPE, + env=env) # Push the task to the watchdog -- it will kill the task # if it goes over the timeout while we keep its stdout