AU: Function to trigger crash reporter.
This CL introduces a new utility function that fork()s and has the
child call abort(), thus triggering the crash reporter. The actual
work is done in a main loop callback to ensure that the stack trace is
the same for all calls to this function.
TEST=unittest (minimal), tested on device - saw crash reporter pick up the crash.
BUG=10739
Review URL: http://codereview.chromium.org/6114002
Change-Id: If3c3c43644173f2307b8498d40881c3b38b938e5
diff --git a/utils.cc b/utils.cc
index 359b6b8..95b5ec9 100644
--- a/utils.cc
+++ b/utils.cc
@@ -8,6 +8,7 @@
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/wait.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
@@ -501,6 +502,27 @@
return true;
}
+namespace {
+// Do the actual trigger. We do it as a main-loop callback to (try to) get a
+// consistent stack trace.
+gboolean TriggerCrashReporterUpload(void* unused) {
+ pid_t pid = fork();
+ CHECK(pid >= 0) << "fork failed"; // fork() failed. Something is very wrong.
+ if (pid == 0) {
+ // We are the child. Crash.
+ abort(); // never returns
+ }
+ // We are the parent. Wait for child to terminate.
+ pid_t result = waitpid(pid, NULL, 0);
+ LOG_IF(ERROR, result < 0) << "waitpid() failed";
+ return FALSE; // Don't call this callback again
+}
+} // namespace {}
+
+void ScheduleCrashReporterUpload() {
+ g_idle_add(&TriggerCrashReporterUpload, NULL);
+}
+
bool SetProcessPriority(ProcessPriority priority) {
int prio = static_cast<int>(priority);
LOG(INFO) << "Setting process priority to " << prio;
diff --git a/utils.h b/utils.h
index 4979636..776fc22 100644
--- a/utils.h
+++ b/utils.h
@@ -141,6 +141,10 @@
// Initiates a system reboot. Returns true on success, false otherwise.
bool Reboot();
+// Schedules a Main Loop callback to trigger the crash reporter to perform an
+// upload as if this process had crashed.
+void ScheduleCrashReporterUpload();
+
// Fuzzes an integer |value| randomly in the range:
// [value - range / 2, value + range - range / 2]
int FuzzInt(int value, unsigned int range);
diff --git a/utils_unittest.cc b/utils_unittest.cc
index d8bc866..185ab9a 100644
--- a/utils_unittest.cc
+++ b/utils_unittest.cc
@@ -255,4 +255,22 @@
EXPECT_EQ(10 * 1024 * 1024 / 4096, block_count);
}
+namespace {
+gboolean TerminateScheduleCrashReporterUploadTest(void* arg) {
+ GMainLoop* loop = reinterpret_cast<GMainLoop*>(arg);
+ g_main_loop_quit(loop);
+ return FALSE; // Don't call this callback again
+}
+} // namespace {}
+
+TEST(UtilsTest, ScheduleCrashReporterUploadTest) {
+ // Not much to test. At least this tests for memory leaks, crashes,
+ // log errors.
+ GMainLoop* loop = g_main_loop_new(g_main_context_default(), FALSE);
+ utils::ScheduleCrashReporterUpload();
+ g_timeout_add_seconds(1, &TerminateScheduleCrashReporterUploadTest, loop);
+ g_main_loop_run(loop);
+ g_main_loop_unref(loop);
+}
+
} // namespace chromeos_update_engine