| 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 | 4 |
| 5 #include "crash-reporter/user_collector.h" | 5 #include "crash-reporter/user_collector.h" |
| 6 | 6 |
| 7 #include <grp.h> // For struct group. | 7 #include <grp.h> // For struct group. |
| 8 #include <pcrecpp.h> |
| 9 #include <pcrecpp.h> |
| 8 #include <pwd.h> // For struct passwd. | 10 #include <pwd.h> // For struct passwd. |
| 9 #include <sys/types.h> // For getpwuid_r, getgrnam_r, WEXITSTATUS. | 11 #include <sys/types.h> // For getpwuid_r, getgrnam_r, WEXITSTATUS. |
| 10 | 12 |
| 11 #include <string> | 13 #include <string> |
| 12 #include <vector> | 14 #include <vector> |
| 13 | 15 |
| 14 #include "base/file_util.h" | 16 #include "base/file_util.h" |
| 15 #include "base/logging.h" | 17 #include "base/logging.h" |
| 16 #include "base/string_util.h" | 18 #include "base/string_util.h" |
| 17 #include "crash-reporter/system_logging.h" | 19 #include "crash-reporter/system_logging.h" |
| 18 #include "gflags/gflags.h" | 20 #include "gflags/gflags.h" |
| 19 | 21 |
| 20 #pragma GCC diagnostic ignored "-Wstrict-aliasing" | 22 #pragma GCC diagnostic ignored "-Wstrict-aliasing" |
| 21 DEFINE_bool(core2md_failure_test, false, "Core2md failure test"); | 23 DEFINE_bool(core2md_failure, false, "Core2md failure test"); |
| 22 DEFINE_bool(directory_failure_test, false, "Spool directory failure test"); | 24 DEFINE_bool(directory_failure, false, "Spool directory failure test"); |
| 23 DEFINE_string(filter_in, "", | 25 DEFINE_string(filter_in, "", |
| 24 "Ignore all crashes but this for testing"); | 26 "Ignore all crashes but this for testing"); |
| 25 #pragma GCC diagnostic error "-Wstrict-aliasing" | 27 #pragma GCC diagnostic error "-Wstrict-aliasing" |
| 26 | 28 |
| 27 static const char kCollectionErrorSignature[] = | 29 static const char kCollectionErrorSignature[] = |
| 28 "crash_reporter-user-collection"; | 30 "crash_reporter-user-collection"; |
| 29 // This procfs file is used to cause kernel core file writing to | 31 // This procfs file is used to cause kernel core file writing to |
| 30 // instead pipe the core file into a user space process. See | 32 // instead pipe the core file into a user space process. See |
| 31 // core(5) man page. | 33 // core(5) man page. |
| 32 static const char kCorePatternFile[] = "/proc/sys/kernel/core_pattern"; | 34 static const char kCorePatternFile[] = "/proc/sys/kernel/core_pattern"; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 61 our_path_ = our_path; | 63 our_path_ = our_path; |
| 62 initialized_ = true; | 64 initialized_ = true; |
| 63 generate_diagnostics_ = generate_diagnostics; | 65 generate_diagnostics_ = generate_diagnostics; |
| 64 } | 66 } |
| 65 | 67 |
| 66 UserCollector::~UserCollector() { | 68 UserCollector::~UserCollector() { |
| 67 } | 69 } |
| 68 | 70 |
| 69 std::string UserCollector::GetPattern(bool enabled) const { | 71 std::string UserCollector::GetPattern(bool enabled) const { |
| 70 if (enabled) { | 72 if (enabled) { |
| 71 return StringPrintf("|%s --signal=%%s --pid=%%p", our_path_.c_str()); | 73 // Combine the three crash attributes into one parameter to try to reduce |
| 74 // the size of the invocation line for crash_reporter since the kernel |
| 75 // has a fixed-sized (128B) buffer that it will truncate into. Note that |
| 76 // the kernel does not support quoted arguments in core_pattern. |
| 77 return StringPrintf("|%s --user=%%p:%%s:%%e", our_path_.c_str()); |
| 72 } else { | 78 } else { |
| 73 return "core"; | 79 return "core"; |
| 74 } | 80 } |
| 75 } | 81 } |
| 76 | 82 |
| 77 bool UserCollector::SetUpInternal(bool enabled) { | 83 bool UserCollector::SetUpInternal(bool enabled) { |
| 78 CHECK(initialized_); | 84 CHECK(initialized_); |
| 79 logger_->LogInfo("%s user crash handling", | 85 logger_->LogInfo("%s user crash handling", |
| 80 enabled ? "Enabling" : "Disabling"); | 86 enabled ? "Enabling" : "Disabling"); |
| 81 if (file_util::WriteFile(FilePath(core_pipe_limit_file_), | 87 if (file_util::WriteFile(FilePath(core_pipe_limit_file_), |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 return false; | 168 return false; |
| 163 } | 169 } |
| 164 const char *number = ids[kind].c_str(); | 170 const char *number = ids[kind].c_str(); |
| 165 char *end_number = NULL; | 171 char *end_number = NULL; |
| 166 *id = strtol(number, &end_number, 10); | 172 *id = strtol(number, &end_number, 10); |
| 167 if (*end_number != '\0') | 173 if (*end_number != '\0') |
| 168 return false; | 174 return false; |
| 169 return true; | 175 return true; |
| 170 } | 176 } |
| 171 | 177 |
| 172 void UserCollector::LogCollectionError(const std::string &error_message) { | |
| 173 error_log_.append(error_message.c_str()); | |
| 174 error_log_.append("\n"); | |
| 175 logger_->LogError(error_message.c_str()); | |
| 176 } | |
| 177 | |
| 178 void UserCollector::EnqueueCollectionErrorLog(pid_t pid, | 178 void UserCollector::EnqueueCollectionErrorLog(pid_t pid, |
| 179 const std::string &exec) { | 179 const std::string &exec) { |
| 180 FilePath crash_path; | 180 FilePath crash_path; |
| 181 logger_->LogInfo("Writing conversion problems as separate crash report."); | 181 logger_->LogInfo("Writing conversion problems as separate crash report."); |
| 182 if (!GetCreatedCrashDirectoryByEuid(0, &crash_path, NULL)) { | 182 if (!GetCreatedCrashDirectoryByEuid(0, &crash_path, NULL)) { |
| 183 logger_->LogError("Could not even get log directory; out of space?"); | 183 logger_->LogError("Could not even get log directory; out of space?"); |
| 184 return; | 184 return; |
| 185 } | 185 } |
| 186 std::string dump_basename = FormatDumpBasename(exec, time(NULL), pid); | 186 std::string dump_basename = FormatDumpBasename(exec, time(NULL), pid); |
| 187 std::string error_log = logger_->get_accumulator(); |
| 188 FilePath diag_log_path = GetCrashPath(crash_path, dump_basename, "diaglog"); |
| 189 if (GetLogContents(FilePath(kDefaultLogConfig), kCollectionErrorSignature, |
| 190 diag_log_path)) { |
| 191 // We load the contents of diag_log into memory and append it to |
| 192 // the error log. We cannot just append to files because we need |
| 193 // to always create new files to prevent attack. |
| 194 std::string diag_log_contents; |
| 195 file_util::ReadFileToString(diag_log_path, &diag_log_contents); |
| 196 error_log.append(diag_log_contents); |
| 197 file_util::Delete(diag_log_path, false); |
| 198 } |
| 187 FilePath log_path = GetCrashPath(crash_path, dump_basename, "log"); | 199 FilePath log_path = GetCrashPath(crash_path, dump_basename, "log"); |
| 188 FilePath meta_path = GetCrashPath(crash_path, dump_basename, "meta"); | 200 FilePath meta_path = GetCrashPath(crash_path, dump_basename, "meta"); |
| 189 // We must use WriteNewFile instead of file_util::WriteFile as we do | 201 // We must use WriteNewFile instead of file_util::WriteFile as we do |
| 190 // not want to write with root access to a symlink that an attacker | 202 // not want to write with root access to a symlink that an attacker |
| 191 // might have created. | 203 // might have created. |
| 192 WriteNewFile(log_path, error_log_.data(), error_log_.length()); | 204 WriteNewFile(log_path, error_log.data(), error_log.length()); |
| 193 AddCrashMetaData("sig", kCollectionErrorSignature); | 205 AddCrashMetaData("sig", kCollectionErrorSignature); |
| 194 WriteCrashMetaData(meta_path, exec, log_path.value()); | 206 WriteCrashMetaData(meta_path, exec, log_path.value()); |
| 195 } | 207 } |
| 196 | 208 |
| 197 bool UserCollector::CopyOffProcFiles(pid_t pid, | 209 bool UserCollector::CopyOffProcFiles(pid_t pid, |
| 198 const FilePath &container_dir) { | 210 const FilePath &container_dir) { |
| 199 if (!file_util::CreateDirectory(container_dir)) { | 211 if (!file_util::CreateDirectory(container_dir)) { |
| 200 LogCollectionError(StringPrintf("Could not create %s", | 212 logger_->LogError("Could not create %s", |
| 201 container_dir.value().c_str())); | 213 container_dir.value().c_str()); |
| 202 return false; | 214 return false; |
| 203 } | 215 } |
| 204 FilePath process_path = GetProcessPath(pid); | 216 FilePath process_path = GetProcessPath(pid); |
| 205 if (!file_util::PathExists(process_path)) { | 217 if (!file_util::PathExists(process_path)) { |
| 206 LogCollectionError(StringPrintf("Path %s does not exist", | 218 logger_->LogError("Path %s does not exist", process_path.value().c_str()); |
| 207 process_path.value().c_str())); | |
| 208 return false; | 219 return false; |
| 209 } | 220 } |
| 210 static const char *proc_files[] = { | 221 static const char *proc_files[] = { |
| 211 "auxv", | 222 "auxv", |
| 212 "cmdline", | 223 "cmdline", |
| 213 "environ", | 224 "environ", |
| 214 "maps", | 225 "maps", |
| 215 "status" | 226 "status" |
| 216 }; | 227 }; |
| 217 for (unsigned i = 0; i < arraysize(proc_files); ++i) { | 228 for (unsigned i = 0; i < arraysize(proc_files); ++i) { |
| 218 if (!file_util::CopyFile(process_path.Append(proc_files[i]), | 229 if (!file_util::CopyFile(process_path.Append(proc_files[i]), |
| 219 container_dir.Append(proc_files[i]))) { | 230 container_dir.Append(proc_files[i]))) { |
| 220 LogCollectionError(StringPrintf("Could not copy %s file", | 231 logger_->LogError("Could not copy %s file", proc_files[i]); |
| 221 proc_files[i])); | |
| 222 return false; | 232 return false; |
| 223 } | 233 } |
| 224 } | 234 } |
| 225 return true; | 235 return true; |
| 226 } | 236 } |
| 227 | 237 |
| 228 bool UserCollector::GetCreatedCrashDirectory(pid_t pid, | 238 bool UserCollector::GetCreatedCrashDirectory(pid_t pid, |
| 229 FilePath *crash_file_path, | 239 FilePath *crash_file_path, |
| 230 bool *out_of_capacity) { | 240 bool *out_of_capacity) { |
| 231 FilePath process_path = GetProcessPath(pid); | 241 FilePath process_path = GetProcessPath(pid); |
| 232 std::string status; | 242 std::string status; |
| 233 if (FLAGS_directory_failure_test) { | 243 if (FLAGS_directory_failure) { |
| 234 LogCollectionError("Purposefully failing to create spool directory"); | 244 logger_->LogError("Purposefully failing to create spool directory"); |
| 235 return false; | 245 return false; |
| 236 } | 246 } |
| 237 if (!file_util::ReadFileToString(process_path.Append("status"), | 247 if (!file_util::ReadFileToString(process_path.Append("status"), |
| 238 &status)) { | 248 &status)) { |
| 239 LogCollectionError("Could not read status file"); | 249 logger_->LogError("Could not read status file"); |
| 250 logger_->LogInfo("Path %s FileExists: %d", |
| 251 process_path.value().c_str(), |
| 252 file_util::DirectoryExists(process_path)); |
| 240 return false; | 253 return false; |
| 241 } | 254 } |
| 242 int process_euid; | 255 int process_euid; |
| 243 if (!GetIdFromStatus(kUserId, kIdEffective, status, &process_euid)) { | 256 if (!GetIdFromStatus(kUserId, kIdEffective, status, &process_euid)) { |
| 244 LogCollectionError("Could not find euid in status file"); | 257 logger_->LogError("Could not find euid in status file"); |
| 245 return false; | 258 return false; |
| 246 } | 259 } |
| 247 if (!GetCreatedCrashDirectoryByEuid(process_euid, | 260 if (!GetCreatedCrashDirectoryByEuid(process_euid, |
| 248 crash_file_path, | 261 crash_file_path, |
| 249 out_of_capacity)) { | 262 out_of_capacity)) { |
| 250 LogCollectionError("Could not create crash directory"); | 263 logger_->LogError("Could not create crash directory"); |
| 251 return false; | 264 return false; |
| 252 } | 265 } |
| 253 return true; | 266 return true; |
| 254 } | 267 } |
| 255 | 268 |
| 256 bool UserCollector::CopyStdinToCoreFile(const FilePath &core_path) { | 269 bool UserCollector::CopyStdinToCoreFile(const FilePath &core_path) { |
| 257 // Copy off all stdin to a core file. | 270 // Copy off all stdin to a core file. |
| 258 FilePath stdin_path("/dev/fd/0"); | 271 FilePath stdin_path("/dev/fd/0"); |
| 259 if (file_util::CopyFile(stdin_path, core_path)) { | 272 if (file_util::CopyFile(stdin_path, core_path)) { |
| 260 return true; | 273 return true; |
| 261 } | 274 } |
| 262 | 275 |
| 263 LogCollectionError("Could not write core file"); | 276 logger_->LogError("Could not write core file"); |
| 264 // If the file system was full, make sure we remove any remnants. | 277 // If the file system was full, make sure we remove any remnants. |
| 265 file_util::Delete(core_path, false); | 278 file_util::Delete(core_path, false); |
| 266 return false; | 279 return false; |
| 267 } | 280 } |
| 268 | 281 |
| 269 bool UserCollector::RunCoreToMinidump(const FilePath &core_path, | 282 bool UserCollector::RunCoreToMinidump(const FilePath &core_path, |
| 270 const FilePath &procfs_directory, | 283 const FilePath &procfs_directory, |
| 271 const FilePath &minidump_path, | 284 const FilePath &minidump_path, |
| 272 const FilePath &temp_directory) { | 285 const FilePath &temp_directory) { |
| 273 FilePath output_path = temp_directory.Append("output"); | 286 FilePath output_path = temp_directory.Append("output"); |
| 274 std::vector<const char *> core2md_arguments; | 287 std::vector<const char *> core2md_arguments; |
| 275 core2md_arguments.push_back(kCoreToMinidumpConverterPath); | 288 core2md_arguments.push_back(kCoreToMinidumpConverterPath); |
| 276 core2md_arguments.push_back(core_path.value().c_str()); | 289 core2md_arguments.push_back(core_path.value().c_str()); |
| 277 core2md_arguments.push_back(procfs_directory.value().c_str()); | 290 core2md_arguments.push_back(procfs_directory.value().c_str()); |
| 278 core2md_arguments.push_back(minidump_path.value().c_str()); | 291 core2md_arguments.push_back(minidump_path.value().c_str()); |
| 279 | 292 |
| 280 if (FLAGS_core2md_failure_test) { | 293 if (FLAGS_core2md_failure) { |
| 281 // To test how core2md errors are propagaged, cause an error | 294 // To test how core2md errors are propagaged, cause an error |
| 282 // by forgetting a required argument. | 295 // by forgetting a required argument. |
| 283 core2md_arguments.pop_back(); | 296 core2md_arguments.pop_back(); |
| 284 } | 297 } |
| 285 | 298 |
| 286 int errorlevel = ForkExecAndPipe(core2md_arguments, | 299 int errorlevel = ForkExecAndPipe(core2md_arguments, |
| 287 output_path.value().c_str()); | 300 output_path.value().c_str()); |
| 288 | 301 |
| 289 std::string output; | 302 std::string output; |
| 290 file_util::ReadFileToString(output_path, &output); | 303 file_util::ReadFileToString(output_path, &output); |
| 291 if (errorlevel != 0) { | 304 if (errorlevel != 0) { |
| 292 LogCollectionError(StringPrintf("Problem during %s [result=%d]: %s", | 305 logger_->LogError("Problem during %s [result=%d]: %s", |
| 293 kCoreToMinidumpConverterPath, | 306 kCoreToMinidumpConverterPath, |
| 294 errorlevel, | 307 errorlevel, |
| 295 output.c_str())); | 308 output.c_str()); |
| 296 return false; | 309 return false; |
| 297 } | 310 } |
| 298 | 311 |
| 299 if (!file_util::PathExists(minidump_path)) { | 312 if (!file_util::PathExists(minidump_path)) { |
| 300 LogCollectionError(StringPrintf("Minidump file %s was not created", | 313 logger_->LogError("Minidump file %s was not created", |
| 301 minidump_path.value().c_str())); | 314 minidump_path.value().c_str()); |
| 302 return false; | 315 return false; |
| 303 } | 316 } |
| 304 return true; | 317 return true; |
| 305 } | 318 } |
| 306 | 319 |
| 307 bool UserCollector::ConvertCoreToMinidump(pid_t pid, | 320 bool UserCollector::ConvertCoreToMinidump(pid_t pid, |
| 308 const FilePath &container_dir, | 321 const FilePath &container_dir, |
| 309 const FilePath &core_path, | 322 const FilePath &core_path, |
| 310 const FilePath &minidump_path) { | 323 const FilePath &minidump_path) { |
| 311 if (!CopyOffProcFiles(pid, container_dir)) { | 324 if (!CopyOffProcFiles(pid, container_dir)) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 327 } | 340 } |
| 328 | 341 |
| 329 return conversion_result; | 342 return conversion_result; |
| 330 } | 343 } |
| 331 | 344 |
| 332 bool UserCollector::ConvertAndEnqueueCrash(int pid, | 345 bool UserCollector::ConvertAndEnqueueCrash(int pid, |
| 333 const std::string &exec, | 346 const std::string &exec, |
| 334 bool *out_of_capacity) { | 347 bool *out_of_capacity) { |
| 335 FilePath crash_path; | 348 FilePath crash_path; |
| 336 if (!GetCreatedCrashDirectory(pid, &crash_path, out_of_capacity)) { | 349 if (!GetCreatedCrashDirectory(pid, &crash_path, out_of_capacity)) { |
| 337 LogCollectionError("Unable to find/create process-specific crash path"); | 350 logger_->LogError("Unable to find/create process-specific crash path"); |
| 338 return false; | 351 return false; |
| 339 } | 352 } |
| 340 | 353 |
| 341 // Directory like /tmp/crash_reporter.1234 which contains the | 354 // Directory like /tmp/crash_reporter.1234 which contains the |
| 342 // procfs entries and other temporary files used during conversion. | 355 // procfs entries and other temporary files used during conversion. |
| 343 FilePath container_dir = FilePath("/tmp").Append( | 356 FilePath container_dir = FilePath("/tmp").Append( |
| 344 StringPrintf("crash_reporter.%d", pid)); | 357 StringPrintf("crash_reporter.%d", pid)); |
| 358 // Delete a pre-existing directory from crash reporter that may have |
| 359 // been left around for diagnostics from a failed conversion attempt. |
| 360 // If we don't, existing files can cause forking to fail. |
| 361 file_util::Delete(container_dir, true); |
| 345 std::string dump_basename = FormatDumpBasename(exec, time(NULL), pid); | 362 std::string dump_basename = FormatDumpBasename(exec, time(NULL), pid); |
| 346 FilePath core_path = GetCrashPath(crash_path, dump_basename, "core"); | 363 FilePath core_path = GetCrashPath(crash_path, dump_basename, "core"); |
| 347 FilePath meta_path = GetCrashPath(crash_path, dump_basename, "meta"); | 364 FilePath meta_path = GetCrashPath(crash_path, dump_basename, "meta"); |
| 348 FilePath minidump_path = GetCrashPath(crash_path, dump_basename, "dmp"); | 365 FilePath minidump_path = GetCrashPath(crash_path, dump_basename, "dmp"); |
| 349 FilePath log_path = GetCrashPath(crash_path, dump_basename, "log"); | 366 FilePath log_path = GetCrashPath(crash_path, dump_basename, "log"); |
| 350 | 367 |
| 351 if (GetLogContents(FilePath(kDefaultLogConfig), exec, log_path)) | 368 if (GetLogContents(FilePath(kDefaultLogConfig), exec, log_path)) |
| 352 AddCrashMetaData("log", log_path.value()); | 369 AddCrashMetaData("log", log_path.value()); |
| 353 | 370 |
| 354 if (!ConvertCoreToMinidump(pid, container_dir, core_path, | 371 if (!ConvertCoreToMinidump(pid, container_dir, core_path, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 369 file_util::Delete(core_path, false); | 386 file_util::Delete(core_path, false); |
| 370 } else { | 387 } else { |
| 371 logger_->LogInfo("Leaving core file at %s due to developer image", | 388 logger_->LogInfo("Leaving core file at %s due to developer image", |
| 372 core_path.value().c_str()); | 389 core_path.value().c_str()); |
| 373 } | 390 } |
| 374 | 391 |
| 375 file_util::Delete(container_dir, true); | 392 file_util::Delete(container_dir, true); |
| 376 return true; | 393 return true; |
| 377 } | 394 } |
| 378 | 395 |
| 379 bool UserCollector::HandleCrash(int signal, int pid, const char *force_exec) { | 396 bool UserCollector::ParseCrashAttributes(const std::string &crash_attributes, |
| 397 pid_t *pid, int *signal, |
| 398 std::string *kernel_supplied_name) { |
| 399 pcrecpp::RE re("(\\d+):(\\d+):(.*)"); |
| 400 return re.FullMatch(crash_attributes, pid, signal, kernel_supplied_name); |
| 401 } |
| 402 |
| 403 bool UserCollector::HandleCrash(const std::string &crash_attributes, |
| 404 const char *force_exec) { |
| 380 CHECK(initialized_); | 405 CHECK(initialized_); |
| 406 int pid = 0; |
| 407 int signal = 0; |
| 408 std::string kernel_supplied_name; |
| 409 |
| 410 if (!ParseCrashAttributes(crash_attributes, &pid, &signal, |
| 411 &kernel_supplied_name)) { |
| 412 logger_->LogError("Invalid parameter: --user=%s", crash_attributes.c_str()); |
| 413 return false; |
| 414 } |
| 415 |
| 381 std::string exec; | 416 std::string exec; |
| 382 if (force_exec) { | 417 if (force_exec) { |
| 383 exec.assign(force_exec); | 418 exec.assign(force_exec); |
| 384 } else if (!GetExecutableBaseNameFromPid(pid, &exec)) { | 419 } else if (!GetExecutableBaseNameFromPid(pid, &exec)) { |
| 385 // If for some reason we don't have the base name, avoid completely | 420 // If we cannot find the exec name, use the kernel supplied name. |
| 386 // failing by indicating an unknown name. | 421 // We don't always use the kernel's since it truncates the name to |
| 387 exec = "unknown"; | 422 // 16 characters. |
| 423 exec = StringPrintf("supplied_%s", kernel_supplied_name.c_str()); |
| 388 } | 424 } |
| 389 | 425 |
| 390 // Allow us to test the crash reporting mechanism successfully even if | 426 // Allow us to test the crash reporting mechanism successfully even if |
| 391 // other parts of the system crash. | 427 // other parts of the system crash. |
| 392 if (!FLAGS_filter_in.empty() && | 428 if (!FLAGS_filter_in.empty() && |
| 393 (FLAGS_filter_in == "none" || | 429 (FLAGS_filter_in == "none" || |
| 394 FLAGS_filter_in != exec)) { | 430 FLAGS_filter_in != exec)) { |
| 395 // We use a different format message to make it more obvious in tests | 431 // We use a different format message to make it more obvious in tests |
| 396 // which crashes are test generated and which are real. | 432 // which crashes are test generated and which are real. |
| 397 logger_->LogWarning("Ignoring crash from %s[%d] while filter_in=%s", | 433 logger_->LogWarning("Ignoring crash from %s[%d] while filter_in=%s.", |
| 398 exec.c_str(), pid, FLAGS_filter_in.c_str()); | 434 exec.c_str(), pid, FLAGS_filter_in.c_str()); |
| 399 return true; | 435 return true; |
| 400 } | 436 } |
| 401 | 437 |
| 402 bool feedback = is_feedback_allowed_function_(); | 438 bool feedback = is_feedback_allowed_function_(); |
| 403 const char *handling_string = "handling"; | 439 const char *handling_string = "handling"; |
| 404 if (!feedback) { | 440 if (!feedback) { |
| 405 handling_string = "ignoring - no consent"; | 441 handling_string = "ignoring - no consent"; |
| 406 } | 442 } |
| 407 | 443 |
| 408 // Treat Chrome crashes as if the user opted-out. We stop counting Chrome | 444 // Treat Chrome crashes as if the user opted-out. We stop counting Chrome |
| 409 // crashes towards user crashes, so user crashes really mean non-Chrome | 445 // crashes towards user crashes, so user crashes really mean non-Chrome |
| 410 // user-space crashes. | 446 // user-space crashes. |
| 411 if (exec == "chrome") { | 447 if (exec == "chrome") { |
| 412 feedback = false; | 448 feedback = false; |
| 413 handling_string = "ignoring - chrome crash"; | 449 handling_string = "ignoring - chrome crash"; |
| 414 } | 450 } |
| 415 | 451 |
| 416 logger_->LogWarning("Received crash notification for %s[%d] sig %d (%s)", | 452 logger_->LogWarning("Received crash notification for %s[%d] sig %d (%s)", |
| 417 exec.c_str(), pid, signal, handling_string); | 453 exec.c_str(), pid, signal, handling_string); |
| 418 | 454 |
| 419 if (feedback) { | 455 if (feedback) { |
| 420 count_crash_function_(); | 456 count_crash_function_(); |
| 421 | 457 |
| 422 if (generate_diagnostics_) { | 458 if (generate_diagnostics_) { |
| 423 bool out_of_capacity = false; | 459 bool out_of_capacity = false; |
| 424 if (!ConvertAndEnqueueCrash(pid, exec, &out_of_capacity)) { | 460 logger_->set_accumulating(true); |
| 461 bool convert_and_enqueue_result = |
| 462 ConvertAndEnqueueCrash(pid, exec, &out_of_capacity); |
| 463 logger_->set_accumulating(false); |
| 464 if (!convert_and_enqueue_result) { |
| 425 if (!out_of_capacity) | 465 if (!out_of_capacity) |
| 426 EnqueueCollectionErrorLog(pid, exec); | 466 EnqueueCollectionErrorLog(pid, exec); |
| 427 return false; | 467 return false; |
| 428 } | 468 } |
| 429 } | 469 } |
| 430 } | 470 } |
| 431 | 471 |
| 432 return true; | 472 return true; |
| 433 } | 473 } |
| OLD | NEW |