toolkit/crashreporter/test/unit/head_crashreporter.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 Components.utils.import("resource://gre/modules/osfile.jsm");
michael@0 2
michael@0 3 function getEventDir() {
michael@0 4 return OS.Path.join(do_get_tempdir().path, "crash-events");
michael@0 5 }
michael@0 6
michael@0 7 /*
michael@0 8 * Run an xpcshell subprocess and crash it.
michael@0 9 *
michael@0 10 * @param setup
michael@0 11 * A string of JavaScript code to execute in the subprocess
michael@0 12 * before crashing. If this is a function and not a string,
michael@0 13 * it will have .toSource() called on it, and turned into
michael@0 14 * a call to itself. (for programmer convenience)
michael@0 15 * This code will be evaluted between crasher_subprocess_head.js
michael@0 16 * and crasher_subprocess_tail.js, so it will have access
michael@0 17 * to everything defined in crasher_subprocess_head.js,
michael@0 18 * which includes "crashReporter", a variable holding
michael@0 19 * the crash reporter service.
michael@0 20 *
michael@0 21 * @param callback
michael@0 22 * A JavaScript function to be called after the subprocess
michael@0 23 * crashes. It will be passed (minidump, extra), where
michael@0 24 * minidump is an nsILocalFile of the minidump file produced,
michael@0 25 * and extra is an object containing the key,value pairs from
michael@0 26 * the .extra file.
michael@0 27 *
michael@0 28 * @param canReturnZero
michael@0 29 * If true, the subprocess may return with a zero exit code.
michael@0 30 * Certain types of crashes may not cause the process to
michael@0 31 * exit with an error.
michael@0 32 */
michael@0 33 function do_crash(setup, callback, canReturnZero)
michael@0 34 {
michael@0 35 // get current process filename (xpcshell)
michael@0 36 let ds = Components.classes["@mozilla.org/file/directory_service;1"]
michael@0 37 .getService(Components.interfaces.nsIProperties);
michael@0 38 let bin = ds.get("CurProcD", Components.interfaces.nsILocalFile);
michael@0 39 bin.append("xpcshell");
michael@0 40 if (!bin.exists()) {
michael@0 41 bin.leafName = "xpcshell.exe";
michael@0 42 do_check_true(bin.exists());
michael@0 43 if (!bin.exists())
michael@0 44 // weird, can't find xpcshell binary?
michael@0 45 do_throw("Can't find xpcshell binary!");
michael@0 46 }
michael@0 47 // get Gre dir (GreD)
michael@0 48 let greD = ds.get("GreD", Components.interfaces.nsILocalFile);
michael@0 49 let headfile = do_get_file("crasher_subprocess_head.js");
michael@0 50 let tailfile = do_get_file("crasher_subprocess_tail.js");
michael@0 51 // run xpcshell -g GreD -f head -e "some setup code" -f tail
michael@0 52 let process = Components.classes["@mozilla.org/process/util;1"]
michael@0 53 .createInstance(Components.interfaces.nsIProcess);
michael@0 54 process.init(bin);
michael@0 55 let args = ['-g', greD.path,
michael@0 56 '-f', headfile.path];
michael@0 57 if (setup) {
michael@0 58 if (typeof(setup) == "function")
michael@0 59 // funky, but convenient
michael@0 60 setup = "("+setup.toSource()+")();";
michael@0 61 args.push('-e', setup);
michael@0 62 }
michael@0 63 args.push('-f', tailfile.path);
michael@0 64
michael@0 65 let env = Components.classes["@mozilla.org/process/environment;1"]
michael@0 66 .getService(Components.interfaces.nsIEnvironment);
michael@0 67
michael@0 68 let crashD = do_get_tempdir();
michael@0 69 crashD.append("crash-events");
michael@0 70 if (!crashD.exists()) {
michael@0 71 crashD.create(crashD.DIRECTORY_TYPE, 0700);
michael@0 72 }
michael@0 73
michael@0 74 env.set("CRASHES_EVENTS_DIR", crashD.path);
michael@0 75
michael@0 76 try {
michael@0 77 process.run(true, args, args.length);
michael@0 78 }
michael@0 79 catch(ex) {} // on Windows we exit with a -1 status when crashing.
michael@0 80 finally {
michael@0 81 env.set("CRASHES_EVENTS_DIR", "");
michael@0 82 }
michael@0 83
michael@0 84 if (!canReturnZero) {
michael@0 85 // should exit with an error (should have crashed)
michael@0 86 do_check_neq(process.exitValue, 0);
michael@0 87 }
michael@0 88
michael@0 89 handleMinidump(callback);
michael@0 90 }
michael@0 91
michael@0 92 function handleMinidump(callback)
michael@0 93 {
michael@0 94 // find minidump
michael@0 95 let minidump = null;
michael@0 96 let en = do_get_tempdir().directoryEntries;
michael@0 97 while (en.hasMoreElements()) {
michael@0 98 let f = en.getNext().QueryInterface(Components.interfaces.nsILocalFile);
michael@0 99 if (f.leafName.substr(-4) == ".dmp") {
michael@0 100 minidump = f;
michael@0 101 break;
michael@0 102 }
michael@0 103 }
michael@0 104
michael@0 105 if (minidump == null)
michael@0 106 do_throw("No minidump found!");
michael@0 107
michael@0 108 let extrafile = minidump.clone();
michael@0 109 extrafile.leafName = extrafile.leafName.slice(0, -4) + ".extra";
michael@0 110
michael@0 111 // Just in case, don't let these files linger.
michael@0 112 do_register_cleanup(function() {
michael@0 113 if (minidump.exists())
michael@0 114 minidump.remove(false);
michael@0 115 if (extrafile.exists())
michael@0 116 extrafile.remove(false);
michael@0 117 });
michael@0 118 do_check_true(extrafile.exists());
michael@0 119 let extra = parseKeyValuePairsFromFile(extrafile);
michael@0 120
michael@0 121 if (callback)
michael@0 122 callback(minidump, extra);
michael@0 123
michael@0 124 if (minidump.exists())
michael@0 125 minidump.remove(false);
michael@0 126 if (extrafile.exists())
michael@0 127 extrafile.remove(false);
michael@0 128 }
michael@0 129
michael@0 130 function do_content_crash(setup, callback)
michael@0 131 {
michael@0 132 do_load_child_test_harness();
michael@0 133 do_test_pending();
michael@0 134
michael@0 135 // Setting the minidump path won't work in the child, so we need to do
michael@0 136 // that here.
michael@0 137 let crashReporter =
michael@0 138 Components.classes["@mozilla.org/toolkit/crash-reporter;1"]
michael@0 139 .getService(Components.interfaces.nsICrashReporter);
michael@0 140 crashReporter.minidumpPath = do_get_tempdir();
michael@0 141
michael@0 142 let headfile = do_get_file("../unit/crasher_subprocess_head.js");
michael@0 143 let tailfile = do_get_file("../unit/crasher_subprocess_tail.js");
michael@0 144 if (setup) {
michael@0 145 if (typeof(setup) == "function")
michael@0 146 // funky, but convenient
michael@0 147 setup = "("+setup.toSource()+")();";
michael@0 148 }
michael@0 149
michael@0 150 let handleCrash = function() {
michael@0 151 try {
michael@0 152 handleMinidump(callback);
michael@0 153 } catch (x) {
michael@0 154 do_report_unexpected_exception(x);
michael@0 155 }
michael@0 156 do_test_finished();
michael@0 157 };
michael@0 158
michael@0 159 sendCommand("load(\"" + headfile.path.replace(/\\/g, "/") + "\");", function()
michael@0 160 sendCommand(setup, function()
michael@0 161 sendCommand("load(\"" + tailfile.path.replace(/\\/g, "/") + "\");",
michael@0 162 function() do_execute_soon(handleCrash)
michael@0 163 )
michael@0 164 )
michael@0 165 );
michael@0 166 }
michael@0 167
michael@0 168 // Import binary APIs via js-ctypes.
michael@0 169 Components.utils.import("resource://test/CrashTestUtils.jsm");
michael@0 170 Components.utils.import("resource://gre/modules/KeyValueParser.jsm");

mercurial