Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Unified Diff: src/platform/crash/crash_dumper.cc

Issue 2128004: Adding in-process crash dumping library and crash uploader (Closed) Base URL: ssh://git@chromiumos-git//chromeos
Patch Set: respond to review and add another test Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/platform/crash/crash_dumper.h ('k') | src/platform/crash/crash_reporter.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/platform/crash/crash_dumper.cc
diff --git a/src/platform/crash/crash_dumper.cc b/src/platform/crash/crash_dumper.cc
new file mode 100644
index 0000000000000000000000000000000000000000..94a82636d4f527bd67bac85e804c5b1f3be5c490
--- /dev/null
+++ b/src/platform/crash/crash_dumper.cc
@@ -0,0 +1,127 @@
+// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <errno.h>
+#include <pwd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "client/linux/handler/exception_handler.h"
+#include "common/linux/linux_libc_support.h"
+#include "common/linux/linux_syscall_support.h"
+#include "crash/crash_dumper.h"
+
+// Define sys_mkdir (sys_open passes mode_t as int, so we do too).
+LSS_INLINE _syscall2(int, mkdir, const char *, pathname, int, mode);
+
+static const char kDefaultUser[] = "chronos";
+static const char kSystemCrashParentPath[] = "/var/spool";
+static const char kSystemCrashPath[] = "/var/spool/crash";
+static const char kUserCrashParentPath[] = "/home/chronos/user";
+static const char kUserCrashPath[] = "/home/chronos/user/crash";
+
+// Pointers to paths, set when crash dumping is enabled.
+static const char *s_crash_path;
+static const char *s_crash_parent_path;
+static mode_t s_dump_directory_mode;
+
+static bool s_any_crashes_occurred = false;
+static scoped_ptr<google_breakpad::ExceptionHandler> s_breakpad_handler;
+
+static bool s_enabled = false;
+
+
+// Prepare the crash path. Must avoid allocating memory.
+static bool PrepareCrashPath() {
+ struct kernel_stat buf;
+ if (sys_stat(s_crash_path, &buf) < 0) {
+ // Dump directory does not exist, so create it and its parent now,
+ // at the time of the crash.
+ sys_mkdir(s_crash_parent_path, 755);
+ sys_mkdir(s_crash_path, s_dump_directory_mode);
+ }
+ return sys_stat(s_crash_path, &buf) == 0;
+}
+
+// Use FilterCallback to avoid recursive crashing.
+// TODO(kmixter): Also use it to avoid enqueuing too many crash dumps
+// system wide - if we get in a crash/restart loop we don't want the entire
+// stateful partition to be filled up.
+static bool FilterCallback(void *) {
+ // This function runs in a compromised context - a crash has already
+ // occurred so memory allocation and libc should be avoided.
+ bool old_any_crashes_occured = s_any_crashes_occurred;
+ s_any_crashes_occurred = true;
+ // The crash path may have been removed or mounted-over, so make sure
+ // there is a container directory. If it fails, not much we can do.
+ PrepareCrashPath();
+ return !old_any_crashes_occured;
+}
+
+static bool GetEffectiveUser(std::string *result) {
+ char storage[256];
+ struct passwd passwd_storage;
+ struct passwd *passwd_result = NULL;
+
+ if (getpwuid_r(geteuid(), &passwd_storage, storage, sizeof(storage),
+ &passwd_result) != 0 || passwd_result == NULL) {
+ return false;
+ }
+
+ *result = passwd_result->pw_name;
+ return true;
+}
+
+void CrashDumper::Enable() {
+ CHECK(!s_enabled) << "Crash handling already enabled";
+
+ std::string name;
+ CHECK(GetEffectiveUser(&name))
+ << "getpwuid_r failed - " << errno
+ << " - crash reporting cannot be enabled";
+
+ if (name == kDefaultUser) {
+ // Crashes as "chronos" when the user is not yet logged in will
+ // still be recorded to /home/chronos/user/crash in the
+ // stateful partition (outside cryptohome). These will eventually
+ // be uploaded when no user is logged in.
+ s_crash_path = kUserCrashPath;
+ s_crash_parent_path = kUserCrashParentPath;
+ s_dump_directory_mode = 0755;
+ } else {
+ s_crash_path = kSystemCrashPath;
+ s_crash_parent_path = kSystemCrashParentPath;
+ // Make the dump directory sticky so any UID can write to
+ // it but not remove another UID's crashes.
+ s_dump_directory_mode = 01777;
+ }
+
+ CHECK(PrepareCrashPath()) << "Unable to create path " << s_crash_path;
+
+ // Begin collecting crashes
+ s_breakpad_handler.reset(new google_breakpad::ExceptionHandler(
+ s_crash_path,
+ FilterCallback,
+ NULL, // No minidump callback - sending happens asynchronously to writing
+ NULL, // No callback context necessary
+ true)); // Install handler now.
+
+ s_enabled = true;
+}
+
+bool CrashDumper::IsEnabled() {
+ return s_enabled;
+}
+
+void CrashDumper::Disable() {
+ CHECK(s_enabled) << "Crash handling was not enabled";
+ s_breakpad_handler.reset(NULL);
+ s_crash_path = NULL;
+ s_crash_parent_path = NULL;
+ s_enabled = false;
+}
« no previous file with comments | « src/platform/crash/crash_dumper.h ('k') | src/platform/crash/crash_reporter.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698