diff options
author | zhurunz@google.com <zhurunz@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-22 05:41:50 +0000 |
---|---|---|
committer | zhurunz@google.com <zhurunz@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-22 05:41:50 +0000 |
commit | 1fcab653da84a27ca76229bcf94fdd799cbd40c6 (patch) | |
tree | 153bca8dd000bcea29cd7411f3f42e65a32841ed /o3d | |
parent | 5e1ed6dcace94125b65e1061e2219672fda9ba1f (diff) | |
download | chromium_src-1fcab653da84a27ca76229bcf94fdd799cbd40c6.zip chromium_src-1fcab653da84a27ca76229bcf94fdd799cbd40c6.tar.gz chromium_src-1fcab653da84a27ca76229bcf94fdd799cbd40c6.tar.bz2 |
Add breakpad.
Review URL: http://codereview.chromium.org/2092021
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@47987 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d')
-rw-r--r-- | o3d/DEPS | 5 | ||||
-rw-r--r-- | o3d/breakpad/breakpad.gyp | 19 | ||||
-rw-r--r-- | o3d/breakpad/linux/breakpad.cc | 215 | ||||
-rw-r--r-- | o3d/breakpad/linux/breakpad.h | 129 | ||||
-rw-r--r-- | o3d/plugin/linux/main_linux.cc | 9 | ||||
-rw-r--r-- | o3d/plugin/plugin.gyp | 14 |
6 files changed, 389 insertions, 2 deletions
@@ -4,12 +4,13 @@ vars = { # When updating the chromium rev, you must also update the nss and sqlite # revs to match the version pulled-in by Chromium's own DEPS in the new rev. "chromium_rev": "37758", + "chromium_breakpad_rev": "47985", "o3d_code_rev": "190", "skia_rev": "488", "gyp_rev": "820", "gtest_rev": "359", "gflags_rev": "30", - "breakpad_rev": "391", + "breakpad_rev": "603", "v8_rev": "3608", "nacl_rev": "1434", } @@ -113,7 +114,7 @@ deps = { Var("chromium_trunk") + "/src/skia@" + Var("chromium_rev"), "breakpad": - Var("chromium_trunk") + "/src/breakpad@" + Var("chromium_rev"), + Var("chromium_trunk") + "/src/breakpad@" + Var("chromium_breakpad_rev"), "base": Var("chromium_trunk") + "/src/base@" + Var("chromium_rev"), diff --git a/o3d/breakpad/breakpad.gyp b/o3d/breakpad/breakpad.gyp index 68e64ae..9623efd 100644 --- a/o3d/breakpad/breakpad.gyp +++ b/o3d/breakpad/breakpad.gyp @@ -68,6 +68,25 @@ ], }, ], + ['OS=="linux"', + { + 'targets': [ + { + 'target_name': 'o3dBreakpad', + 'type': 'static_library', + 'sources': [ + 'linux/breakpad.cc', + 'linux/breakpad.h', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '../../breakpad/src', + ], + }, + }, + ], + }, + ], ], } diff --git a/o3d/breakpad/linux/breakpad.cc b/o3d/breakpad/linux/breakpad.cc new file mode 100644 index 0000000..92656dd --- /dev/null +++ b/o3d/breakpad/linux/breakpad.cc @@ -0,0 +1,215 @@ +/* + * Copyright 2010, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "breakpad.h" + +#if defined(LINUX) +#include <sys/stat.h> +#endif // defined(LINUX) + +namespace o3d { +#if defined(WIN32) +static const std::string kBreakpadProduct = "Google_O3D_Plugin"; +#elif defined(OSX) +static const std::string kBreakpadProduct = "Google_O3D_Plugin_Mac"; +#elif defined(LINUX) +static const std::string kBreakpadProduct = "Google_O3D_Plugin_Linux"; +#endif +static const std::string kBreakpadVersion = "unknown"; +static const std::string kBreakpadGUID = "unknown"; +static const std::string kBreakpadEmail = "unknown"; +#ifdef _DEBUG +static const std::string kBreakpadServer = + "http://clients2.google.com/cr/staging_report"; +#else +static const std::string kBreakpadServer = + "http://clients2.google.com/cr/report"; +#endif +static const std::string kBreakpadDumpFilenameTemplate = + "/tmp/google-o3d-plugin-minidump-XXXXXX"; + +//TODO(zhurunz): Add/use decent path utility functions. + +bool Breakpad::Initialize() { + if (NULL != breakpad_) + return true; + + // Set default configuration. + set_product(kBreakpadProduct); + set_version(kBreakpadVersion); + set_guid(kBreakpadGUID); + set_email(kBreakpadEmail); + set_path("/tmp/"); + set_server(kBreakpadServer); + + // TODO(zhurunz): consider using HANDLE_CRASHES + // Setup callback. + breakpad_ = new + google_breakpad::ExceptionHandler(path_.c_str(), + NULL, /* filter callback */ + BreakpadCallback, + this, + true /* install handlers */); + + return (NULL != breakpad_); +} + +bool Breakpad::Shutdown() { + delete breakpad_; + breakpad_ = NULL; + return true; +} + +#if defined(LINUX) +bool Breakpad::BuildDumpFilename(char* filename, + int len, + const char* dump_path, + const char* minidump_id) { + const int dump_path_len = strlen(dump_path); + const int minidump_id_len = strlen(minidump_id); + int len_needed = dump_path_len + minidump_id_len + + 4 /* ".dmp" */ + 1 /* NUL */; + if (len_needed > len) + return false; + + filename[0] = '\0'; + std::strcat(filename, dump_path); + std::strcat(filename, minidump_id); + std::strcat(filename, ".dmp"); + + return true; +} + +bool Breakpad::SendDumpFile(const char* filename) { + struct stat st; + if (stat(filename, &st) != 0 || st.st_size <= 0) + return false; + + google_breakpad::GoogleCrashdumpUploader + uploader(product_.c_str(), + version_.c_str(), + guid_.c_str(), + ptime_.c_str(), + ctime_.c_str(), + email_.c_str(), + comments_.c_str(), + filename, + server_.c_str(), + proxy_.c_str(), + passwd_.c_str()); + return uploader.Upload(); +} + +bool Breakpad::GenerateAndSendDumpFile( + const std::map<std::string, std::string>* extra_params) { + + // Create pipe. + int fds[2]; + if (0 != pipe(fds)) + return false; + + std::string filename = kBreakpadDumpFilenameTemplate; + if (NULL == mktemp(const_cast<char*>(filename.c_str()))) { + close(fds[0]); + close(fds[1]); + return false; + } + + // We must breakpad minidump the child process. + // Minidump ourself would crash in breakpad. + const pid_t child = fork(); + if (0 == child) { + close(fds[1]); + char b; + HANDLE_EINTR(read(fds[0], &b, sizeof(b))); + close(fds[0]); + syscall(__NR_exit); + } + if (-1 == child) { + close(fds[0]); + close(fds[1]); + return false; + } + + close(fds[0]); + + // Create minidump. + google_breakpad::ExceptionHandler::CrashContext context; + memset(&context, 0, sizeof(context)); + if (!WriteMinidump(filename.c_str(), child, + &context, sizeof(context))) { + close(fds[1]); + return false; + } + + // Upload minidump. + bool ret = SendDumpFile(filename.c_str()); + unlink(filename.c_str()); + close(fds[1]); + return ret; +} + +bool Breakpad::OnBreakpadCallback(const char* dump_path, + const char* minidump_id, + bool succeeded) { + // WARNING: this code runs in a compromised context. It may not call into + // libc nor allocate memory normally. + if (!succeeded) + return succeeded; + + // Build dump filename. + char filename[256]; + if (!BuildDumpFilename(filename, sizeof(filename), + dump_path, minidump_id)) + return false; + + // TODO(zhurunz): Change in-proc upload to out-proc upload. + // TODO(zhurunz): Sync with other teams in ChromeOS and figure out if + // we could have a GC proc to upload all dumps on ChromeOS/Linux. + bool ret = SendDumpFile(filename); + unlink(filename); + + return ret; +} +#endif // defined(LINUX) + +bool BreakpadCallback(const char* dump_path, + const char* minidump_id, + void* context, + bool succeeded) { + Breakpad* breakpad = reinterpret_cast<Breakpad*>(context); + if (NULL == breakpad) + return false; + + return breakpad->OnBreakpadCallback(dump_path, minidump_id, succeeded); +} + +} // namespace o3d diff --git a/o3d/breakpad/linux/breakpad.h b/o3d/breakpad/linux/breakpad.h new file mode 100644 index 0000000..cbba468 --- /dev/null +++ b/o3d/breakpad/linux/breakpad.h @@ -0,0 +1,129 @@ +/* + * Copyright 2010, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef O3D_LINUX_BREAKPAD_H_ +#define O3D_LINUX_BREAKPAD_H_ + +#include <string> + +#if defined(LINUX) +#include "client/linux/handler/exception_handler.h" +#include "client/linux/minidump_writer/minidump_writer.h" +#include "common/linux/linux_syscall_support.h" +#include "common/linux/google_crashdump_uploader.h" +#endif // defined(LINUX) + +namespace o3d { +class Breakpad { + public: + const std::string& product() const { return product_; } + void set_product(const std::string & product) { product_ = product; } + + const std::string& version() const { return version_; } + void set_version(const std::string & version) { version_ = version; } + + const std::string& guid() const { return guid_; } + void set_guid(const std::string & guid) { guid_ = guid; } + + const std::string& email() const { return email_; } + void set_email(const std::string & email) { email_ = email; } + + const std::string& path() const { return path_; } + void set_path(const std::string & path) { path_ = path; } + + const std::string& server() const { return server_; } + void set_server(const std::string & server) { server_ = server; } + + bool Initialize(); + bool Shutdown(); + // Any data in extra_params is currently discarded. + bool GenerateAndSendDumpFile( + const std::map<std::string, std::string>* extra_params); + + private: + static bool BuildDumpFilename(char* filename, + int len, + const char* dump_path, + const char* minidump_id); + + // This is virtual to allow unittest to overwirte it and not sending + // out minidump file in test. + virtual bool SendDumpFile(const char* filename); + + // Invoked by friend function BreakpadCallback + bool OnBreakpadCallback(const char* dump_path, + const char* minidump_id, + bool succeeded); + + friend bool BreakpadCallback(const char* dump_path, + const char* minidump_id, + void* context, + bool succeeded); + + std::string product_; + std::string version_; + std::string guid_; + std::string ptime_; + std::string ctime_; + std::string email_; + std::string comments_; + std::string path_; + std::string server_; + std::string proxy_; + std::string passwd_; + + google_breakpad::ExceptionHandler* breakpad_; +}; + +// Breakpad minidump callback +// A friend function of Breakpad to invoke OnBreakpadCallback. +bool BreakpadCallback(const char* dump_path, + const char* minidump_id, + void* context, + bool succeeded); + + +#if defined(LINUX) +// This provides a wrapper around system calls which may be +// interrupted by a signal and return EINTR. See man 7 signal. +#define HANDLE_EINTR(x) ({ \ + typeof(x) __eintr_result__; \ + do { \ + __eintr_result__ = x; \ + } while (__eintr_result__ == -1 && errno == EINTR); \ + __eintr_result__;\ +}) +#endif // defined(LINUX) + +} // namespace o3d + +#endif // O3D_LINUX_BREAKPAD_H_ diff --git a/o3d/plugin/linux/main_linux.cc b/o3d/plugin/linux/main_linux.cc index 80bd3d5..7e3ffb3 100644 --- a/o3d/plugin/linux/main_linux.cc +++ b/o3d/plugin/linux/main_linux.cc @@ -40,6 +40,7 @@ #include "base/command_line.h" #include "base/logging.h" #include "base/scoped_ptr.h" +#include "o3d/breakpad/linux/breakpad.h" #include "plugin/cross/main.h" #include "plugin/cross/out_of_memory.h" #include "plugin/cross/whitelist.h" @@ -61,6 +62,8 @@ base::AtExitManager g_at_exit_manager; bool g_xembed_support = false; +o3d::Breakpad g_breakpad; + #ifdef O3D_PLUGIN_ENV_VARS_FILE static const char *kEnvVarsFilePath = O3D_PLUGIN_ENV_VARS_FILE; #endif @@ -622,6 +625,10 @@ NPError InitializePlugin() { if (!o3d::SetupOutOfMemoryHandler()) return NPERR_MODULE_LOAD_FAILED_ERROR; + // Setup breakpad + g_breakpad.Initialize(); + g_breakpad.set_version(O3D_PLUGIN_VERSION); + CommandLine::Init(0, NULL); InitLogging("debug.log", logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG, @@ -682,6 +689,8 @@ NPError EXPORT_SYMBOL OSCALL NP_Shutdown(void) { CommandLine::Reset(); + g_breakpad.Shutdown(); + return NPERR_NO_ERROR; } diff --git a/o3d/plugin/plugin.gyp b/o3d/plugin/plugin.gyp index e7092e7..503994f 100644 --- a/o3d/plugin/plugin.gyp +++ b/o3d/plugin/plugin.gyp @@ -267,6 +267,10 @@ ], ['OS == "linux"', { + 'dependencies': [ + '../../breakpad/breakpad.gyp:breakpad_client', + '../breakpad/breakpad.gyp:o3dBreakpad', + ], 'sources': [ 'linux/config.cc', 'linux/envvars.cc', @@ -288,6 +292,7 @@ # the --as-needed flag. '-lCgGL', '-lGLEW', + '-ldl', # Used by breakpad '-lrt', # Directs the linker to only generate dependencies on libraries # that we actually use. Must come last. @@ -297,6 +302,15 @@ '<!@(pkg-config --libs-only-l xt)', ], 'conditions' : [ + ['target_arch=="ia32"', + { # Used by breakpad + # TODO(zhurunz) Remove the deps on libglog.a + 'libraries': [ + '-Lbreakpad/src/third_party/linux/lib/glog', + '-lglog', + ], + }, + ], ['plugin_rpath != ""', { 'ldflags': [ |