OLD | NEW |
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // |
| 5 // Simple wrapper and basic configuration of Google breakpad. We try |
| 6 // to avoid using any unnecessary code (like libbase) to make it as |
| 7 // non-intrusive as possible to link in this library. |
4 | 8 |
5 #include <errno.h> | 9 #include <errno.h> |
6 #include <pwd.h> | 10 #include <pwd.h> |
| 11 #include <stddef.h> |
7 #include <sys/stat.h> | 12 #include <sys/stat.h> |
8 #include <sys/types.h> | 13 #include <sys/types.h> |
9 #include <unistd.h> | 14 #include <unistd.h> |
10 | 15 |
11 #include "base/file_path.h" | |
12 #include "base/file_util.h" | |
13 #include "base/logging.h" | |
14 #include "client/linux/handler/exception_handler.h" | 16 #include "client/linux/handler/exception_handler.h" |
15 #include "common/linux/linux_libc_support.h" | 17 #include "common/linux/linux_libc_support.h" |
16 #include "common/linux/linux_syscall_support.h" | 18 #include "common/linux/linux_syscall_support.h" |
17 #include "crash/crash_dumper.h" | 19 #include "crash/crash_dumper.h" |
18 | 20 |
19 // Define sys_mkdir (sys_open passes mode_t as int, so we do too). | 21 // Define sys_mkdir (sys_open passes mode_t as int, so we do too). |
20 LSS_INLINE _syscall2(int, mkdir, const char *, pathname, int, mode); | 22 LSS_INLINE _syscall2(int, mkdir, const char *, pathname, int, mode); |
21 | 23 |
22 static const char kDefaultUser[] = "chronos"; | 24 static const char kDefaultUser[] = "chronos"; |
23 static const char kSystemCrashParentPath[] = "/var/spool"; | 25 static const char kSystemCrashParentPath[] = "/var/spool"; |
24 static const char kSystemCrashPath[] = "/var/spool/crash"; | 26 static const char kSystemCrashPath[] = "/var/spool/crash"; |
25 static const char kUserCrashParentPath[] = "/home/chronos/user"; | 27 static const char kUserCrashParentPath[] = "/home/chronos/user"; |
26 static const char kUserCrashPath[] = "/home/chronos/user/crash"; | 28 static const char kUserCrashPath[] = "/home/chronos/user/crash"; |
27 | 29 |
28 // Pointers to paths, set when crash dumping is enabled. | 30 // Pointers to paths, set when crash dumping is enabled. |
29 static const char *s_crash_path; | 31 static const char *s_crash_path; |
30 static const char *s_crash_parent_path; | 32 static const char *s_crash_parent_path; |
31 static mode_t s_dump_directory_mode; | 33 static mode_t s_dump_directory_mode; |
32 | 34 |
33 static bool s_any_crashes_occurred = false; | 35 static bool s_any_crashes_occurred = false; |
34 static scoped_ptr<google_breakpad::ExceptionHandler> s_breakpad_handler; | 36 static google_breakpad::ExceptionHandler *s_breakpad_handler; |
35 | 37 |
36 static bool s_enabled = false; | 38 static bool s_enabled = false; |
37 | 39 |
| 40 #define CHECK_CONDITION(_cond, _message) \ |
| 41 do { if (!(_cond)) { fputs(_message, stderr); abort(); } } while(false) |
| 42 |
| 43 // This static object will cause anything that links in this object to get |
| 44 // crash handling for the duration of this file's scope. |
| 45 static CrashDumper g_crash_dumper; |
| 46 |
38 | 47 |
39 // Prepare the crash path. Must avoid allocating memory. | 48 // Prepare the crash path. Must avoid allocating memory. |
40 static bool PrepareCrashPath() { | 49 static bool PrepareCrashPath() { |
41 struct kernel_stat buf; | 50 struct kernel_stat buf; |
42 if (sys_stat(s_crash_path, &buf) < 0) { | 51 if (sys_stat(s_crash_path, &buf) < 0) { |
43 // Dump directory does not exist, so create it and its parent now, | 52 // Dump directory does not exist, so create it and its parent now, |
44 // at the time of the crash. | 53 // at the time of the crash. |
45 sys_mkdir(s_crash_parent_path, 755); | 54 sys_mkdir(s_crash_parent_path, 755); |
46 sys_mkdir(s_crash_path, s_dump_directory_mode); | 55 sys_mkdir(s_crash_path, s_dump_directory_mode); |
47 } | 56 } |
(...skipping 23 matching lines...) Expand all Loading... |
71 if (getpwuid_r(geteuid(), &passwd_storage, storage, sizeof(storage), | 80 if (getpwuid_r(geteuid(), &passwd_storage, storage, sizeof(storage), |
72 &passwd_result) != 0 || passwd_result == NULL) { | 81 &passwd_result) != 0 || passwd_result == NULL) { |
73 return false; | 82 return false; |
74 } | 83 } |
75 | 84 |
76 *result = passwd_result->pw_name; | 85 *result = passwd_result->pw_name; |
77 return true; | 86 return true; |
78 } | 87 } |
79 | 88 |
80 void CrashDumper::Enable() { | 89 void CrashDumper::Enable() { |
81 CHECK(!s_enabled) << "Crash handling already enabled"; | 90 CHECK_CONDITION(!s_enabled, "Crash handling already enabled"); |
82 | 91 |
83 std::string name; | 92 std::string name; |
84 CHECK(GetEffectiveUser(&name)) | 93 CHECK_CONDITION(GetEffectiveUser(&name), |
85 << "getpwuid_r failed - " << errno | 94 "getpwuid_r failed, cannot enable crash reporting"); |
86 << " - crash reporting cannot be enabled"; | |
87 | 95 |
88 if (name == kDefaultUser) { | 96 if (name == kDefaultUser) { |
89 // Crashes as "chronos" when the user is not yet logged in will | 97 // Crashes as "chronos" when the user is not yet logged in will |
90 // still be recorded to /home/chronos/user/crash in the | 98 // still be recorded to /home/chronos/user/crash in the |
91 // stateful partition (outside cryptohome). These will eventually | 99 // stateful partition (outside cryptohome). These will eventually |
92 // be uploaded when no user is logged in. | 100 // be uploaded when no user is logged in. |
93 s_crash_path = kUserCrashPath; | 101 s_crash_path = kUserCrashPath; |
94 s_crash_parent_path = kUserCrashParentPath; | 102 s_crash_parent_path = kUserCrashParentPath; |
95 s_dump_directory_mode = 0755; | 103 s_dump_directory_mode = 0755; |
96 } else { | 104 } else { |
97 s_crash_path = kSystemCrashPath; | 105 s_crash_path = kSystemCrashPath; |
98 s_crash_parent_path = kSystemCrashParentPath; | 106 s_crash_parent_path = kSystemCrashParentPath; |
99 // Make the dump directory sticky so any UID can write to | 107 // Make the dump directory sticky so any UID can write to |
100 // it but not remove another UID's crashes. | 108 // it but not remove another UID's crashes. |
101 s_dump_directory_mode = 01777; | 109 s_dump_directory_mode = 01777; |
102 } | 110 } |
103 | 111 |
104 CHECK(PrepareCrashPath()) << "Unable to create path " << s_crash_path; | 112 CHECK_CONDITION(PrepareCrashPath(), "Unable to create crash path"); |
105 | 113 |
106 // Begin collecting crashes | 114 // Begin collecting crashes |
107 s_breakpad_handler.reset(new google_breakpad::ExceptionHandler( | 115 s_breakpad_handler = new google_breakpad::ExceptionHandler( |
108 s_crash_path, | 116 s_crash_path, |
109 FilterCallback, | 117 FilterCallback, |
110 NULL, // No minidump callback - sending happens asynchronously to writing | 118 NULL, // No minidump callback - sending happens asynchronously to writing |
111 NULL, // No callback context necessary | 119 NULL, // No callback context necessary |
112 true)); // Install handler now. | 120 true); // Install handler now. |
113 | 121 |
114 s_enabled = true; | 122 s_enabled = true; |
115 } | 123 } |
116 | 124 |
117 bool CrashDumper::IsEnabled() { | 125 bool CrashDumper::IsEnabled() { |
118 return s_enabled; | 126 return s_enabled; |
119 } | 127 } |
120 | 128 |
121 void CrashDumper::Disable() { | 129 void CrashDumper::Disable() { |
122 CHECK(s_enabled) << "Crash handling was not enabled"; | 130 CHECK_CONDITION(s_enabled, "Crash handling was not enabled"); |
123 s_breakpad_handler.reset(NULL); | 131 delete s_breakpad_handler; |
| 132 s_breakpad_handler = NULL; |
124 s_crash_path = NULL; | 133 s_crash_path = NULL; |
125 s_crash_parent_path = NULL; | 134 s_crash_parent_path = NULL; |
126 s_enabled = false; | 135 s_enabled = false; |
127 } | 136 } |
OLD | NEW |