summaryrefslogtreecommitdiffstats
path: root/o3d/breakpad/linux/breakpad.cc
diff options
context:
space:
mode:
Diffstat (limited to 'o3d/breakpad/linux/breakpad.cc')
-rw-r--r--o3d/breakpad/linux/breakpad.cc215
1 files changed, 215 insertions, 0 deletions
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