summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorthestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-17 05:55:51 +0000
committerthestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-17 05:55:51 +0000
commit912c64520e0e9f22bd49e43c7ee102e3b9de66a7 (patch)
tree7eb719597f880b6687c4c5094f83034529378229
parent48e4c173c27c8b539b0719c96985e50651b80d3b (diff)
downloadchromium_src-912c64520e0e9f22bd49e43c7ee102e3b9de66a7.zip
chromium_src-912c64520e0e9f22bd49e43c7ee102e3b9de66a7.tar.gz
chromium_src-912c64520e0e9f22bd49e43c7ee102e3b9de66a7.tar.bz2
Include output of "lsb_release -d" in crash reports.
/etc/lsb-release does not exist on all distros, and sometimes it does not provide any useful info. Whereas all LSB complaint distros return useful data with the lsb_release command. Review URL: http://codereview.chromium.org/155653 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20936 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--base/linux_util.cc33
-rw-r--r--base/linux_util.h6
-rw-r--r--chrome/app/breakpad_linux.cc106
-rw-r--r--chrome/app/breakpad_linux.h21
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.cc50
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.h1
-rw-r--r--chrome/browser/renderer_host/render_crash_handler_host_linux.cc27
7 files changed, 176 insertions, 68 deletions
diff --git a/base/linux_util.cc b/base/linux_util.cc
index a58ee99..604980b 100644
--- a/base/linux_util.cc
+++ b/base/linux_util.cc
@@ -2,10 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "linux_util.h"
+#include "base/linux_util.h"
#include <stdlib.h>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/process_util.h"
+
namespace base {
uint8_t* BGRAToRGBA(const uint8_t* pixels, int width, int height, int stride) {
@@ -28,4 +33,30 @@ uint8_t* BGRAToRGBA(const uint8_t* pixels, int width, int height, int stride) {
return new_pixels;
}
+// We use this static string to hold the Linux distro info. If we
+// crash, the crash handler code will send this in the crash dump.
+std::string linux_distro = "Unknown";
+
+std::string GetLinuxDistro() {
+ static bool checked_distro = false;
+ if (!checked_distro) {
+ std::vector<std::string> argv;
+ argv.push_back("lsb_release");
+ argv.push_back("-d");
+ std::string output;
+ base::GetAppOutput(CommandLine(argv), &output);
+ if (output.length() > 0) {
+ // lsb_release -d should return: Description:<tab>Distro Info
+ static const std::string field = "Description:\t";
+ if (output.compare(0, field.length(), field) == 0)
+ linux_distro = output.substr(field.length());
+ }
+ // We do this check only once per process. If it fails, there's
+ // little reason to believe it will work if we attempt to run
+ // lsb_release again.
+ checked_distro = true;
+ }
+ return linux_distro;
+}
+
} // namespace base
diff --git a/base/linux_util.h b/base/linux_util.h
index aa418cc..973a2b0 100644
--- a/base/linux_util.h
+++ b/base/linux_util.h
@@ -7,6 +7,8 @@
#include <stdint.h>
+#include <string>
+
namespace base {
// Makes a copy of |pixels| with the ordering changed from BGRA to RGBA.
@@ -14,6 +16,10 @@ namespace base {
// it's assumed to be 4 * |width|.
uint8_t* BGRAToRGBA(const uint8_t* pixels, int width, int height, int stride);
+// Get the Linux Distro if we can, or return "Unknown", similar to
+// GetWinVersion() in base/win_util.h.
+std::string GetLinuxDistro();
+
} // namespace base
#endif // BASE_LINUX_UTIL_H__
diff --git a/chrome/app/breakpad_linux.cc b/chrome/app/breakpad_linux.cc
index 2f75d0a..d9c41fd 100644
--- a/chrome/app/breakpad_linux.cc
+++ b/chrome/app/breakpad_linux.cc
@@ -16,6 +16,7 @@
#include "base/eintr_wrapper.h"
#include "base/file_version_info_linux.h"
#include "base/global_descriptors_posix.h"
+#include "base/linux_util.h"
#include "base/path_service.h"
#include "base/rand_util.h"
#include "base/string_util.h"
@@ -42,17 +43,11 @@ static void write_uint64_hex(char* output, uint64_t v) {
}
}
-pid_t UploadCrashDump(const char* filename,
- const char* process_type,
- unsigned process_type_length,
- const char* crash_url,
- unsigned crash_url_length,
- const char* guid,
- unsigned guid_length) {
+pid_t UploadCrashDump(const BreakpadInfo& info) {
// WARNING: this code runs in a compromised context. It may not call into
// libc nor allocate memory normally.
- const int dumpfd = sys_open(filename, O_RDONLY, 0);
+ const int dumpfd = sys_open(info.filename, O_RDONLY, 0);
if (dumpfd < 0) {
static const char msg[] = "Cannot upload crash dump: failed to open\n";
sys_write(2, msg, sizeof(msg));
@@ -144,6 +139,16 @@ pid_t UploadCrashDump(const char* filename,
// BOUNDARY \r\n (27, 28)
//
// zero or more:
+ // Content-Disposition: form-data; name="ptype" \r\n \r\n (0..4)
+ // abcdef \r\n (5, 6)
+ // BOUNDARY \r\n (7, 8)
+ //
+ // zero or more:
+ // Content-Disposition: form-data; name="lsb-release" \r\n \r\n (0..4)
+ // abcdef \r\n (5, 6)
+ // BOUNDARY \r\n (7, 8)
+ //
+ // zero or more:
// Content-Disposition: form-data; name="url-chunk-1" \r\n \r\n (0..5)
// abcdef \r\n (6, 7)
// BOUNDARY \r\n (8, 9)
@@ -166,6 +171,7 @@ pid_t UploadCrashDump(const char* filename,
"Content-Type: application/octet-stream";
static const char url_chunk_msg[] = "url-chunk-";
static const char process_type_msg[] = "ptype";
+ static const char distro_msg[] = "lsb-release";
struct kernel_iovec iov[29];
iov[0].iov_base = mime_boundary;
@@ -226,8 +232,8 @@ pid_t UploadCrashDump(const char* filename,
iov[24].iov_base = const_cast<char*>(rn);
iov[24].iov_len = sizeof(rn);
- iov[25].iov_base = const_cast<char*>(guid);
- iov[25].iov_len = guid_length;
+ iov[25].iov_base = const_cast<char*>(info.guid);
+ iov[25].iov_len = info.guid_length;
iov[26].iov_base = const_cast<char*>(rn);
iov[26].iov_len = sizeof(rn);
@@ -238,7 +244,7 @@ pid_t UploadCrashDump(const char* filename,
sys_writev(fd, iov, 29);
- if (process_type_length) {
+ if (info.process_type_length) {
iov[0].iov_base = const_cast<char*>(form_data_msg);
iov[0].iov_len = sizeof(form_data_msg) - 1;
iov[1].iov_base = const_cast<char*>(process_type_msg);
@@ -250,8 +256,8 @@ pid_t UploadCrashDump(const char* filename,
iov[4].iov_base = const_cast<char*>(rn);
iov[4].iov_len = sizeof(rn);
- iov[5].iov_base = const_cast<char*>(process_type);
- iov[5].iov_len = process_type_length;
+ iov[5].iov_base = const_cast<char*>(info.process_type);
+ iov[5].iov_len = info.process_type_length;
iov[6].iov_base = const_cast<char*>(rn);
iov[6].iov_len = sizeof(rn);
iov[7].iov_base = mime_boundary;
@@ -262,8 +268,32 @@ pid_t UploadCrashDump(const char* filename,
sys_writev(fd, iov, 9);
}
- if (crash_url_length) {
- unsigned i = 0, done = 0;
+ if (info.distro_length) {
+ iov[0].iov_base = const_cast<char*>(form_data_msg);
+ iov[0].iov_len = sizeof(form_data_msg) - 1;
+ iov[1].iov_base = const_cast<char*>(distro_msg);
+ iov[1].iov_len = sizeof(distro_msg) - 1;
+ iov[2].iov_base = const_cast<char*>(quote_msg);
+ iov[2].iov_len = sizeof(quote_msg);
+ iov[3].iov_base = const_cast<char*>(rn);
+ iov[3].iov_len = sizeof(rn);
+ iov[4].iov_base = const_cast<char*>(rn);
+ iov[4].iov_len = sizeof(rn);
+
+ iov[5].iov_base = const_cast<char*>(info.distro);
+ iov[5].iov_len = info.distro_length;
+ iov[6].iov_base = const_cast<char*>(rn);
+ iov[6].iov_len = sizeof(rn);
+ iov[7].iov_base = mime_boundary;
+ iov[7].iov_len = sizeof(mime_boundary) - 1;
+ iov[8].iov_base = const_cast<char*>(rn);
+ iov[8].iov_len = sizeof(rn);
+
+ sys_writev(fd, iov, 9);
+ }
+
+ if (info.crash_url_length) {
+ unsigned i = 0, done = 0, crash_url_length = info.crash_url_length;
static const unsigned kMaxCrashChunkSize = 64;
static const unsigned kMaxUrlLength = 8 * kMaxCrashChunkSize;
if (crash_url_length > kMaxUrlLength)
@@ -289,7 +319,7 @@ pid_t UploadCrashDump(const char* filename,
const unsigned len = crash_url_length > kMaxCrashChunkSize ?
kMaxCrashChunkSize : crash_url_length;
- iov[6].iov_base = const_cast<char*>(crash_url + done);
+ iov[6].iov_base = const_cast<char*>(info.crash_url + done);
iov[6].iov_len = len;
iov[7].iov_base = const_cast<char*>(rn);
iov[7].iov_len = sizeof(rn);
@@ -402,7 +432,7 @@ pid_t UploadCrashDump(const char* filename,
sys_write(2, id_buf, my_strlen(id_buf));
sys_write(2, "\n", 1);
}
- sys_unlink(filename);
+ sys_unlink(info.filename);
sys_unlink(buf);
sys__exit(0);
}
@@ -437,6 +467,12 @@ namespace google_update {
extern std::string linux_guid;
}
+// This is defined in base/linux_util.cc, it's the static string containing the
+// user's distro info. We send this in the crash report.
+namespace base {
+extern std::string linux_distro;
+}
+
static bool CrashDone(const char* dump_path,
const char* minidump_id,
void* context,
@@ -458,8 +494,17 @@ static bool CrashDone(const char* dump_path,
memcpy(path + dump_path_len + 1 + minidump_id_len, ".dmp", 4);
path[dump_path_len + 1 + minidump_id_len + 4] = 0;
- UploadCrashDump(path, "browser", 7, NULL, 0, google_update::linux_guid.data(),
- google_update::linux_guid.length());
+ BreakpadInfo info;
+ info.filename = path;
+ info.process_type = "browser";
+ info.process_type_length = 7;
+ info.crash_url = NULL;
+ info.crash_url_length = 0;
+ info.guid = google_update::linux_guid.data();
+ info.guid_length = google_update::linux_guid.length();
+ info.distro = base::linux_distro.data();
+ info.distro_length = base::linux_distro.length();
+ UploadCrashDump(info);
return true;
}
@@ -481,33 +526,39 @@ extern std::string active_url;
static bool
RendererCrashHandler(const void* crash_context, size_t crash_context_size,
void* context) {
- const int fd = (int) context;
+ const int fd = reinterpret_cast<int>(context);
int fds[2];
socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
char guid[kGuidSize] = {0};
char crash_url[kMaxActiveURLSize + 1] = {0};
+ char distro[kDistroSize + 1] = {0};
const unsigned guid_len = std::min(google_update::linux_guid.size(),
kGuidSize);
const unsigned crash_url_len =
std::min(child_process_logging::active_url.size(), kMaxActiveURLSize);
+ const unsigned distro_len =
+ std::min(base::linux_distro.size(), kDistroSize);
memcpy(guid, google_update::linux_guid.data(), guid_len);
memcpy(crash_url, child_process_logging::active_url.data(), crash_url_len);
+ memcpy(distro, base::linux_distro.data(), distro_len);
// The length of the control message:
static const unsigned kControlMsgSize = CMSG_SPACE(sizeof(int));
struct kernel_msghdr msg;
my_memset(&msg, 0, sizeof(struct kernel_msghdr));
- struct kernel_iovec iov[3];
+ struct kernel_iovec iov[4];
iov[0].iov_base = const_cast<void*>(crash_context);
iov[0].iov_len = crash_context_size;
iov[1].iov_base = guid;
iov[1].iov_len = kGuidSize + 1;
iov[2].iov_base = crash_url;
iov[2].iov_len = kMaxActiveURLSize + 1;
+ iov[3].iov_base = distro;
+ iov[3].iov_len = kDistroSize + 1;
msg.msg_iov = iov;
- msg.msg_iovlen = 3;
+ msg.msg_iovlen = 4;
char cmsg[kControlMsgSize];
memset(cmsg, 0, kControlMsgSize);
msg.msg_control = cmsg;
@@ -545,6 +596,7 @@ void InitCrashReporter() {
if (process_type.empty()) {
if (!GoogleUpdateSettings::GetCollectStatsConsent())
return;
+ base::GetLinuxDistro(); // Initialize base::linux_distro if needed.
EnableCrashDumping();
} else if (process_type == switches::kRendererProcess ||
process_type == switches::kZygoteProcess) {
@@ -553,8 +605,16 @@ void InitCrashReporter() {
// dir. Instead, we set a command line flag for these processes.
if (!parsed_command_line.HasSwitch(switches::kRendererCrashDump))
return;
- google_update::linux_guid = WideToASCII(
+ // Get the guid and linux distro from the command line switch.
+ std::string switch_value = WideToASCII(
parsed_command_line.GetSwitchValue(switches::kRendererCrashDump));
+ size_t separator = switch_value.find(",");
+ if (separator != std::string::npos) {
+ google_update::linux_guid = switch_value.substr(0, separator);
+ base::linux_distro = switch_value.substr(separator + 1);
+ } else {
+ google_update::linux_guid = switch_value;
+ }
EnableRendererCrashDumping();
}
}
diff --git a/chrome/app/breakpad_linux.h b/chrome/app/breakpad_linux.h
index 977adf0..518cf42 100644
--- a/chrome/app/breakpad_linux.h
+++ b/chrome/app/breakpad_linux.h
@@ -10,14 +10,21 @@ extern void InitCrashReporter();
#if defined(GOOGLE_CHROME_BUILD)
static const unsigned kMaxActiveURLSize = 1024;
static const unsigned kGuidSize = 32; // 128 bits = 32 chars in hex.
+static const unsigned kDistroSize = 128;
-extern int UploadCrashDump(const char* filename,
- const char* process_type,
- unsigned process_type_length,
- const char* crash_url,
- unsigned crash_url_length,
- const char* guid,
- unsigned guid_length);
+struct BreakpadInfo {
+ const char* filename;
+ const char* process_type;
+ unsigned process_type_length;
+ const char* crash_url;
+ unsigned crash_url_length;
+ const char* guid;
+ unsigned guid_length;
+ const char* distro;
+ unsigned distro_length;
+};
+
+extern int UploadCrashDump(const BreakpadInfo& info);
#endif // defined(GOOGLE_CHROME_BUILD)
#endif // CHROME_APP_BREAKPAD_LINUX_H_
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc
index bde0294..bad0e3e 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -10,11 +10,14 @@
#include "build/build_config.h"
#include <algorithm>
+#include <limits>
+#include <vector>
-#include "app/app_switches.h"
-#if defined(OS_WIN)
-#include "app/win_util.h"
+#if defined(OS_POSIX)
+#include <utility> // for pair<>
#endif
+
+#include "app/app_switches.h"
#include "base/command_line.h"
#include "base/field_trial.h"
#include "base/linked_ptr.h"
@@ -54,7 +57,11 @@
#include "chrome/installer/util/google_update_settings.h"
#include "grit/generated_resources.h"
-#if defined(OS_LINUX)
+#if defined(OS_WIN)
+#include "app/win_util.h"
+#include "chrome/browser/sandbox_policy.h"
+#elif defined(OS_LINUX)
+#include "base/linux_util.h"
#include "chrome/browser/zygote_host_linux.h"
#include "chrome/browser/renderer_host/render_crash_handler_host_linux.h"
#include "chrome/browser/renderer_host/render_sandbox_host_linux.h"
@@ -62,22 +69,6 @@
using WebKit::WebCache;
-#if defined(OS_WIN)
-
-// TODO(port): see comment by the only usage of RenderViewHost in this file.
-#include "chrome/browser/renderer_host/render_view_host.h"
-
-
-// Once the above TODO is finished, then this block is all Windows-specific
-// files.
-#include "base/win_util.h"
-#include "chrome/browser/sandbox_policy.h"
-#include "sandbox/src/sandbox.h"
-#elif defined(OS_POSIX)
-// TODO(port): Remove temporary scaffolding after porting the above headers.
-#include "chrome/common/temp_scaffolding_stubs.h"
-#endif
-
#include "third_party/skia/include/core/SkBitmap.h"
@@ -401,7 +392,8 @@ bool BrowserRenderProcessHost::Init() {
#if defined(OS_LINUX)
if (GoogleUpdateSettings::GetCollectStatsConsent())
cmd_line.AppendSwitchWithValue(switches::kRendererCrashDump,
- ASCIIToWide(google_update::linux_guid));
+ ASCIIToWide(google_update::linux_guid +
+ "," + base::GetLinuxDistro()));
#endif
cmd_line.AppendSwitchWithValue(switches::kProcessType,
@@ -451,7 +443,7 @@ bool BrowserRenderProcessHost::Init() {
process = Singleton<ZygoteHost>()->ForkRenderer(cmd_line.argv(), mapping);
zygote_child_ = true;
} else {
-#endif
+#endif // defined(OS_LINUX)
// NOTE: This code is duplicated with plugin_process_host.cc, but
// there's not a good place to de-duplicate it.
base::file_handle_mapping_vector fds_to_map;
@@ -467,13 +459,13 @@ bool BrowserRenderProcessHost::Init() {
const int sandbox_fd =
Singleton<RenderSandboxHostLinux>()->GetRendererSocket();
fds_to_map.push_back(std::make_pair(sandbox_fd, kSandboxIPCChannel + 3));
-#endif
+#endif // defined(OS_LINUX)
base::LaunchApp(cmd_line.argv(), fds_to_map, false, &process);
zygote_child_ = false;
#if defined(OS_LINUX)
}
-#endif
-#endif
+#endif // defined(OS_LINUX)
+#endif // defined(OS_WIN)
if (!process) {
channel_.reset();
@@ -527,7 +519,7 @@ void BrowserRenderProcessHost::ReceivedBadMessage(uint16 msg_type) {
void BrowserRenderProcessHost::WidgetRestored() {
// Verify we were properly backgrounded.
- DCHECK(backgrounded_ == (visible_widgets_ == 0));
+ DCHECK_EQ(backgrounded_, (visible_widgets_ == 0));
visible_widgets_++;
visited_link_updater_->Update(this);
SetBackgrounded(false);
@@ -538,9 +530,9 @@ void BrowserRenderProcessHost::WidgetHidden() {
if (backgrounded_)
return;
- DCHECK(backgrounded_ == (visible_widgets_ == 0));
+ DCHECK_EQ(backgrounded_, (visible_widgets_ == 0));
visible_widgets_--;
- DCHECK(visible_widgets_ >= 0);
+ DCHECK_GE(visible_widgets_, 0);
if (visible_widgets_ == 0) {
DCHECK(!backgrounded_);
SetBackgrounded(true);
@@ -918,7 +910,7 @@ void BrowserRenderProcessHost::SetBackgrounded(bool backgrounded) {
// which causes random crashes in the browser process. Our hack for now
// is to not invoke the SetPriorityClass API if the dll is loaded.
should_set_backgrounded = (GetModuleHandle(L"cbstext.dll") == NULL);
-#endif // OS_WIN
+#endif // OS_WIN
if (should_set_backgrounded) {
bool rv = process_.SetProcessBackgrounded(backgrounded);
diff --git a/chrome/browser/renderer_host/browser_render_process_host.h b/chrome/browser/renderer_host/browser_render_process_host.h
index 5230b5e..f02a1d0 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.h
+++ b/chrome/browser/renderer_host/browser_render_process_host.h
@@ -7,6 +7,7 @@
#include "build/build_config.h"
+#include <map>
#include <string>
#include "base/process.h"
diff --git a/chrome/browser/renderer_host/render_crash_handler_host_linux.cc b/chrome/browser/renderer_host/render_crash_handler_host_linux.cc
index 6a60a6a..5c99e5f 100644
--- a/chrome/browser/renderer_host/render_crash_handler_host_linux.cc
+++ b/chrome/browser/renderer_host/render_crash_handler_host_linux.cc
@@ -12,6 +12,7 @@
#include <sys/uio.h>
#include <unistd.h>
+#include <string>
#include <vector>
#include "base/eintr_wrapper.h"
@@ -202,13 +203,14 @@ void RenderCrashHandlerHostLinux::OnFileCanReadWithoutBlocking(int fd) {
sizeof(google_breakpad::ExceptionHandler::CrashContext);
struct msghdr msg = {0};
- struct iovec iov[3];
+ struct iovec iov[4];
char crash_context[kCrashContextSize];
char guid[kGuidSize + 1];
char crash_url[kMaxActiveURLSize + 1];
+ char distro[kDistroSize + 1];
char control[kControlMsgSize];
const ssize_t expected_msg_size = sizeof(crash_context) + sizeof(guid) +
- sizeof(crash_url);
+ sizeof(crash_url) + sizeof(distro);
iov[0].iov_base = crash_context;
iov[0].iov_len = sizeof(crash_context);
@@ -216,8 +218,10 @@ void RenderCrashHandlerHostLinux::OnFileCanReadWithoutBlocking(int fd) {
iov[1].iov_len = sizeof(guid);
iov[2].iov_base = crash_url;
iov[2].iov_len = sizeof(crash_url);
+ iov[3].iov_base = distro;
+ iov[3].iov_len = sizeof(distro);
msg.msg_iov = iov;
- msg.msg_iovlen = 3;
+ msg.msg_iovlen = 4;
msg.msg_control = control;
msg.msg_controllen = kControlMsgSize;
@@ -251,7 +255,7 @@ void RenderCrashHandlerHostLinux::OnFileCanReadWithoutBlocking(int fd) {
if (hdr->cmsg_type == SCM_RIGHTS) {
const unsigned len = hdr->cmsg_len -
(((uint8_t*)CMSG_DATA(hdr)) - (uint8_t*)hdr);
- DCHECK(len % sizeof(int) == 0);
+ DCHECK_EQ(len % sizeof(int), 0u);
const unsigned num_fds = len / sizeof(int);
if (num_fds > 1 || num_fds == 0) {
// A nasty renderer could try and send us too many descriptors and
@@ -320,10 +324,17 @@ void RenderCrashHandlerHostLinux::OnFileCanReadWithoutBlocking(int fd) {
HANDLE_EINTR(sendmsg(signal_fd, &msg, MSG_DONTWAIT | MSG_NOSIGNAL));
HANDLE_EINTR(close(signal_fd));
- UploadCrashDump(minidump_filename.c_str(),
- "renderer", 8,
- crash_url, strlen(crash_url),
- guid, strlen(guid));
+ BreakpadInfo info;
+ info.filename = minidump_filename.c_str();
+ info.process_type = "renderer";
+ info.process_type_length = 8;
+ info.crash_url = crash_url;
+ info.crash_url_length = strlen(crash_url);
+ info.guid = guid;
+ info.guid_length = strlen(guid);
+ info.distro = distro;
+ info.distro_length = strlen(distro);
+ UploadCrashDump(info);
}
void RenderCrashHandlerHostLinux::WillDestroyCurrentMessageLoop() {