crash-reporter: when exe symlink read fails send diags and still ignore chrome crashes
Change-Id: I0f43d5f61936ebb6420c357e58df45761facd4d0
BUG=6299
TEST=unit tests and UserCrash/CrashSender
Review URL: http://codereview.chromium.org/6480009
diff --git a/crash_reporter/crash_reporter.cc b/crash_reporter/crash_reporter.cc
index ffe6cdf..ab4c5ba 100644
--- a/crash_reporter/crash_reporter.cc
+++ b/crash_reporter/crash_reporter.cc
@@ -148,10 +148,13 @@
return 0;
}
+ // Accumulate logs to help in diagnosing failures during user collection.
+ s_system_log.set_accumulating(true);
// Handle the crash, get the name of the process from procfs.
- if (!user_collector->HandleCrash(FLAGS_user, NULL)) {
+ bool handled = user_collector->HandleCrash(FLAGS_user, NULL);
+ s_system_log.set_accumulating(false);
+ if (!handled)
return 1;
- }
return 0;
}
diff --git a/crash_reporter/user_collector.cc b/crash_reporter/user_collector.cc
index a6dd091..6e6c765 100644
--- a/crash_reporter/user_collector.cc
+++ b/crash_reporter/user_collector.cc
@@ -114,6 +114,9 @@
buffer.reset(new char[max_size + 1]);
ssize_t size = readlink(symlink.value().c_str(), buffer.get(), max_size);
if (size < 0) {
+ int saved_errno = errno;
+ logger_->LogError("Readlink failed on %s with %d",
+ symlink.value().c_str(), saved_errno);
return false;
}
buffer[size] = 0;
@@ -136,8 +139,25 @@
bool UserCollector::GetExecutableBaseNameFromPid(uid_t pid,
std::string *base_name) {
FilePath target;
- if (!GetSymlinkTarget(GetProcessPath(pid).Append("exe"), &target))
+ FilePath process_path = GetProcessPath(pid);
+ FilePath exe_path = process_path.Append("exe");
+ if (!GetSymlinkTarget(exe_path, &target)) {
+ logger_->LogInfo("GetSymlinkTarget failed - Path %s DirectoryExists: %d",
+ process_path.value().c_str(),
+ file_util::DirectoryExists(process_path));
+ // Try to further diagnose exe readlink failure cause.
+ struct stat buf;
+ int stat_result = stat(exe_path.value().c_str(), &buf);
+ int saved_errno = errno;
+ if (stat_result < 0) {
+ logger_->LogInfo("stat %s failed: %d %d", exe_path.value().c_str(),
+ stat_result, saved_errno);
+ } else {
+ logger_->LogInfo("stat %s succeeded: st_mode=%d",
+ exe_path.value().c_str(), buf.st_mode);
+ }
return false;
+ }
*base_name = target.BaseName().value();
return true;
}
@@ -247,7 +267,7 @@
if (!file_util::ReadFileToString(process_path.Append("status"),
&status)) {
logger_->LogError("Could not read status file");
- logger_->LogInfo("Path %s FileExists: %d",
+ logger_->LogInfo("Path %s DirectoryExists: %d",
process_path.value().c_str(),
file_util::DirectoryExists(process_path));
return false;
@@ -444,7 +464,7 @@
// Treat Chrome crashes as if the user opted-out. We stop counting Chrome
// crashes towards user crashes, so user crashes really mean non-Chrome
// user-space crashes.
- if (exec == "chrome") {
+ if (exec == "chrome" || exec == "supplied_chrome") {
feedback = false;
handling_string = "ignoring - chrome crash";
}
@@ -457,10 +477,8 @@
if (generate_diagnostics_) {
bool out_of_capacity = false;
- logger_->set_accumulating(true);
bool convert_and_enqueue_result =
ConvertAndEnqueueCrash(pid, exec, &out_of_capacity);
- logger_->set_accumulating(false);
if (!convert_and_enqueue_result) {
if (!out_of_capacity)
EnqueueCollectionErrorLog(pid, exec);
diff --git a/crash_reporter/user_collector.h b/crash_reporter/user_collector.h
index 851d587..21ef14b 100644
--- a/crash_reporter/user_collector.h
+++ b/crash_reporter/user_collector.h
@@ -58,6 +58,7 @@
FRIEND_TEST(UserCollectorTest, CopyOffProcFilesBadPath);
FRIEND_TEST(UserCollectorTest, CopyOffProcFilesBadPid);
FRIEND_TEST(UserCollectorTest, CopyOffProcFilesOK);
+ FRIEND_TEST(UserCollectorTest, GetExecutableBaseNameFromPid);
FRIEND_TEST(UserCollectorTest, GetIdFromStatus);
FRIEND_TEST(UserCollectorTest, GetProcessPath);
FRIEND_TEST(UserCollectorTest, GetSymlinkTarget);
diff --git a/crash_reporter/user_collector_test.cc b/crash_reporter/user_collector_test.cc
index 53e227c..9a1d687 100644
--- a/crash_reporter/user_collector_test.cc
+++ b/crash_reporter/user_collector_test.cc
@@ -158,6 +158,17 @@
ASSERT_EQ(s_crashes, 0);
}
+TEST_F(UserCollectorTest, HandleSuppliedChromeCrashWithMetrics) {
+ s_metrics = true;
+ collector_.HandleCrash("0:2:chrome", NULL);
+ ASSERT_NE(std::string::npos,
+ logging_.log().find(
+ "Received crash notification for supplied_chrome[0] sig 2"));
+ ASSERT_NE(std::string::npos,
+ logging_.log().find("(ignoring - chrome crash)"));
+ ASSERT_EQ(s_crashes, 0);
+}
+
TEST_F(UserCollectorTest, GetProcessPath) {
FilePath path = collector_.GetProcessPath(100);
ASSERT_EQ("/proc/100", path.value());
@@ -167,7 +178,9 @@
FilePath result;
ASSERT_FALSE(collector_.GetSymlinkTarget(FilePath("/does_not_exist"),
&result));
-
+ ASSERT_NE(std::string::npos,
+ logging_.log().find(
+ "Readlink failed on /does_not_exist with 2"));
std::string long_link;
for (int i = 0; i < 50; ++i)
long_link += "0123456789";
@@ -185,6 +198,29 @@
}
}
+TEST_F(UserCollectorTest, GetExecutableBaseNameFromPid) {
+ std::string base_name;
+ EXPECT_FALSE(collector_.GetExecutableBaseNameFromPid(0, &base_name));
+ EXPECT_NE(std::string::npos,
+ logging_.log().find(
+ "Readlink failed on /proc/0/exe with 2"));
+ EXPECT_NE(std::string::npos,
+ logging_.log().find(
+ "GetSymlinkTarget failed - Path "
+ "/proc/0 DirectoryExists: 0"));
+ EXPECT_NE(std::string::npos,
+ logging_.log().find(
+ "stat /proc/0/exe failed: -1 2"));
+
+ logging_.clear();
+ pid_t my_pid = getpid();
+ EXPECT_TRUE(collector_.GetExecutableBaseNameFromPid(my_pid, &base_name));
+ EXPECT_EQ(std::string::npos,
+ logging_.log().find(
+ "Readlink failed"));
+ EXPECT_EQ("user_collector_test", base_name);
+}
+
TEST_F(UserCollectorTest, GetIdFromStatus) {
int id = 1;
EXPECT_FALSE(collector_.GetIdFromStatus(UserCollector::kUserId,