diff options
author | thestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-17 05:55:51 +0000 |
---|---|---|
committer | thestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-17 05:55:51 +0000 |
commit | 912c64520e0e9f22bd49e43c7ee102e3b9de66a7 (patch) | |
tree | 7eb719597f880b6687c4c5094f83034529378229 | |
parent | 48e4c173c27c8b539b0719c96985e50651b80d3b (diff) | |
download | chromium_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.cc | 33 | ||||
-rw-r--r-- | base/linux_util.h | 6 | ||||
-rw-r--r-- | chrome/app/breakpad_linux.cc | 106 | ||||
-rw-r--r-- | chrome/app/breakpad_linux.h | 21 | ||||
-rw-r--r-- | chrome/browser/renderer_host/browser_render_process_host.cc | 50 | ||||
-rw-r--r-- | chrome/browser/renderer_host/browser_render_process_host.h | 1 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_crash_handler_host_linux.cc | 27 |
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() { |