Bug 1379857 - Record Rust panics for child process crashes. r=dmajor

Install crash reporter's panic hook in child processes (and also delay the main
process installation until we know crash reporter is enabled).

When collecting child crash annotations, read the Rust panic message if it
exists.

MozReview-Commit-ID: Gfp2E8IHjw8

--HG--
extra : rebase_source : 9e261f399e7c54fc262a1500cf2514ddd1012406
This commit is contained in:
J. Ryan Stinnett 2017-07-12 14:41:19 -05:00
Родитель 98a8e93fd9
Коммит 50ecb4bb87
4 изменённых файлов: 94 добавлений и 3 удалений

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

@ -1391,7 +1391,14 @@ PrepareChildExceptionTimeAnnotations()
WriteAnnotation(apiData, "OOMAllocationSize", oomAllocationSizeBuffer);
}
if (gMozCrashReason) {
char* rust_panic_reason;
size_t rust_panic_len;
if (get_rust_panic_reason(&rust_panic_reason, &rust_panic_len)) {
// rust_panic_reason is not null-terminated.
WriteLiteral(apiData, "MozCrashReason=");
apiData.WriteBuffer(rust_panic_reason, rust_panic_len);
WriteLiteral(apiData, "\n");
} else if (gMozCrashReason) {
WriteAnnotation(apiData, "MozCrashReason", gMozCrashReason);
}
@ -1594,8 +1601,6 @@ nsresult SetExceptionHandler(nsIFile* aXREDirectory,
if (gExceptionHandler)
return NS_ERROR_ALREADY_INITIALIZED;
install_rust_panic_hook();
#if !defined(DEBUG) || defined(MOZ_WIDGET_GONK)
// In non-debug builds, enable the crash reporter by default, and allow
// disabling it with the MOZ_CRASHREPORTER_DISABLE environment variable.
@ -1822,6 +1827,8 @@ nsresult SetExceptionHandler(nsIFile* aXREDirectory,
oldTerminateHandler = std::set_terminate(&TerminateHandler);
install_rust_panic_hook();
InitThreadAnnotation();
return NS_OK;
@ -3780,6 +3787,8 @@ SetRemoteExceptionHandler(const nsACString& crashPipe)
oldTerminateHandler = std::set_terminate(&TerminateHandler);
install_rust_panic_hook();
// we either do remote or nothing, no fallback to regular crash reporting
return gExceptionHandler->IsOutOfProcess();
}
@ -3827,6 +3836,8 @@ SetRemoteExceptionHandler()
oldTerminateHandler = std::set_terminate(&TerminateHandler);
install_rust_panic_hook();
// we either do remote or nothing, no fallback to regular crash reporting
return gExceptionHandler->IsOutOfProcess();
}
@ -3856,6 +3867,8 @@ SetRemoteExceptionHandler(const nsACString& crashPipe)
oldTerminateHandler = std::set_terminate(&TerminateHandler);
install_rust_panic_hook();
// we either do remote or nothing, no fallback to regular crash reporting
return gExceptionHandler->IsOutOfProcess();
}

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

@ -145,6 +145,13 @@ function handleMinidump(callback) {
}
}
/**
* Helper for testing a content process crash.
*
* This variant accepts a setup function which runs in the content process
* to set data as needed _before_ the crash. The tail file triggers a generic
* crash after setup.
*/
function do_content_crash(setup, callback) {
do_load_child_test_harness();
do_test_pending();
@ -192,6 +199,55 @@ function do_content_crash(setup, callback) {
});
}
/**
* Helper for testing a content process crash.
*
* This variant accepts a trigger function which runs in the content process
* and does something to _trigger_ the crash.
*/
function do_triggered_content_crash(trigger, callback) {
do_load_child_test_harness();
do_test_pending();
// Setting the minidump path won't work in the child, so we need to do
// that here.
let crashReporter =
Components.classes["@mozilla.org/toolkit/crash-reporter;1"]
.getService(Components.interfaces.nsICrashReporter);
crashReporter.minidumpPath = do_get_tempdir();
/* import-globals-from ../unit/crasher_subprocess_head.js */
let headfile = do_get_file("../unit/crasher_subprocess_head.js");
if (trigger) {
if (typeof(trigger) == "function") {
// funky, but convenient
trigger = "(" + trigger.toSource() + ")();";
}
}
let handleCrash = function() {
let id = getMinidump().leafName.slice(0, -4);
Services.crashmanager.ensureCrashIsPresent(id).then(() => {
try {
handleMinidump(callback);
} catch (x) {
do_report_unexpected_exception(x);
}
do_test_finished();
});
};
do_get_profile();
makeFakeAppDir().then(() => {
sendCommand("load(\"" + headfile.path.replace(/\\/g, "/") + "\");", () =>
sendCommand(trigger, () =>
do_execute_soon(handleCrash)
)
);
});
}
// Import binary APIs via js-ctypes.
Components.utils.import("resource://test/CrashTestUtils.jsm");
Components.utils.import("resource://gre/modules/KeyValueParser.jsm");

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

@ -0,0 +1,21 @@
/* import-globals-from ../unit/head_crashreporter.js */
load("../unit/head_crashreporter.js");
function run_test() {
if (!("@mozilla.org/toolkit/crash-reporter;1" in Components.classes)) {
dump("INFO | test_content_rust_panic.js | Can't test crashreporter in a non-libxul build.\n");
return;
}
// Try crashing with a Rust panic
do_triggered_content_crash(
function() {
Components.classes["@mozilla.org/xpcom/debug;1"]
.getService(Components.interfaces.nsIDebug2)
.rustPanic("OH NO");
},
function(mdump, extra) {
do_check_eq(extra.MozCrashReason, "OH NO");
}
);
}

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

@ -12,3 +12,4 @@ support-files =
skip-if = os != 'win'
[test_content_memory_list.js]
skip-if = os != 'win'
[test_content_rust_panic.js]