[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[vidalia-svn] r3841: Move the functions for setting up the exception handler and (vidalia/branches/breakpad/src/vidalia)



Author: edmanm
Date: 2009-06-12 01:39:13 -0400 (Fri, 12 Jun 2009)
New Revision: 3841

Added:
   vidalia/branches/breakpad/src/vidalia/CrashReporter.cpp
   vidalia/branches/breakpad/src/vidalia/CrashReporter.h
Modified:
   vidalia/branches/breakpad/src/vidalia/main.cpp
Log:

Move the functions for setting up the exception handler and crash reporter
out of main.cpp and into their own file and namespace. Also add the code
for launching the crash reporting application from the exception handler.


Added: vidalia/branches/breakpad/src/vidalia/CrashReporter.cpp
===================================================================
--- vidalia/branches/breakpad/src/vidalia/CrashReporter.cpp	                        (rev 0)
+++ vidalia/branches/breakpad/src/vidalia/CrashReporter.cpp	2009-06-12 05:39:13 UTC (rev 3841)
@@ -0,0 +1,159 @@
+/*
+**  This file is part of Vidalia, and is subject to the license terms in the
+**  LICENSE file, found in the top level directory of this distribution. If you
+**  did not receive the LICENSE file with this file, you may obtain it from the
+**  Vidalia source package distributed by the Vidalia Project at
+**  http://www.vidalia-project.net/. No part of Vidalia, including this file,
+**  may be copied, modified, propagated, or distributed except according to the
+**  terms described in the LICENSE file.
+*/
+
+/*
+** \file CrashReporter.h
+** \version $Id$
+** \brief General routines to install a Breakpad-based exception handler and
+** set options related to launching the crash reporting application.
+*/
+
+#include "CrashReporter.h"
+#include "Vidalia.h"
+
+#if defined(Q_OS_WIN32)
+#include <client/windows/handler/exception_handler.h>
+#elif defined(Q_OS_MAC)
+#include <client/mac/handler/exception_handler.h>
+#elif defined(Q_OS_LINUX)
+#include <client/linux/handler/exception_handler.h>
+#elif defined(Q_OS_SOLARIS)
+#include <client/solaris/handler/exception_handler.h>
+#endif
+
+#include <QString>
+#include <QFileInfo>
+#include <QDir>
+
+
+namespace CrashReporter
+{
+/** Defines the maximum length of the command line arguments used to restart
+ * the crashed application by the crash reporter.
+ */
+#define MAX_CMD_LEN 32768
+
+/** Pointer to the Breakpad-installed exception handler called if Vidalia
+ * crashes.
+ */
+static google_breakpad::ExceptionHandler *exceptionHandler = 0;
+
+/** If true, the crash reporting application will be displayed when the
+ * Breakpad-installed exception handler is called. Otherwise, the system
+ * will handle the exception itself.
+ */
+static bool showCrashReporter = true;
+
+/** Absolute path of the crash reporting application that will be launched
+ * from the exception handler.
+ * \sa setup_exception_handler()
+ */
+static wchar_t crashReporterAppPath[MAX_PATH_LEN + 1] = L"";
+
+
+/** Breakpad-installed exception handler. This function gets called in the
+ * event of a crash. If <b>showCrashReporter</b> is true, this will execute
+ * the crash reporting application, passing it the name and location of the
+ * generated minidump, the absolute path to the (now crashed) Vidalia
+ * executable, and any arguments that may be needed to restart Vidalia.
+ */
+static bool
+minidump_callback(const wchar_t *dump, const wchar_t *id, void *context,
+#if defined(Q_OS_WIN32)
+                  EXCEPTION_POINTERS *exInfo,
+                  MDRawAssertionInfo *assertionInfo,
+#endif
+                  bool succeeded)
+{
+  if (! succeeded || ! showCrashReporter)
+    return false;
+
+  /* Launch the crash reporter with the name and location of the minidump */
+#if defined(Q_OS_WIN32)
+  PROCESS_INFORMATION pi;
+  STARTUPINFOW si;
+
+  ZeroMemory(&pi, sizeof(pi));
+  ZeroMemory(&si, sizeof(si));
+  si.cb = sizeof(si);
+  si.dwFlags = STARTF_USESHOWWINDOW;
+  si.wShowWindow = SW_SHOWDEFAULT;
+
+  BOOL rc = CreateProcessW((LPWSTR)crashReporterAppPath, (LPWSTR)NULL,
+                           NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+  if (rc) {
+    CloseHandle(pi.hThread);
+    CloseHandle(pi.hProcess);
+  }
+  TerminateProcess(GetCurrentProcess(), 1);
+  return true;
+#else
+  return false;
+#endif
+}
+
+bool
+install_exception_handler(const QString &dumpPath)
+{
+  /* Create a directory for the crash dumps if it doesn't already exist */
+  QDir dumpDir(dumpPath);
+  if (! dumpDir.exists() && ! dumpDir.mkdir("."))
+    return false;
+
+  /* Create the exception handler and specify where the dumps should go */
+  exceptionHandler = new google_breakpad::ExceptionHandler(
+                            dumpDir.absolutePath().toStdWString(),
+                            NULL,
+                            minidump_callback,
+                            NULL,
+#if defined(Q_OS_WIN32)
+                            google_breakpad::ExceptionHandler::HANDLER_ALL);
+#else
+                            true);
+#endif
+  if (! exceptionHandler)
+    return true;
+
+  return true;
+}
+
+void
+remove_exception_handler()
+{
+  if (exceptionHandler) {
+    delete exceptionHandler;
+    exceptionHandler = 0;
+  }
+}
+
+bool
+set_crash_reporter(const QString &crashReporter)
+{
+  QString appPath = crashReporter;
+
+  /* Wrap the given executable in quotes if it contains spaces */
+  if (appPath.contains(" "))
+    appPath = "\"" + appPath + "\"";
+
+  if (appPath.length() <= CrashReporter::MAX_PATH_LEN) {
+    appPath.toWCharArray(crashReporterAppPath);
+    crashReporterAppPath[appPath.length()] = L'\0';
+    showCrashReporter = true;
+  } else {
+    /* If  the given path is longer than MAX_PATH_LEN, no crash reporting
+     * application will be set since the user's platform wouldn't be able to
+     * execute it anyway.
+     */
+    showCrashReporter = false;
+  }
+  return showCrashReporter;
+}
+
+};


Property changes on: vidalia/branches/breakpad/src/vidalia/CrashReporter.cpp
___________________________________________________________________
Added: svn:keywords
   + Id
Added: svn:eol-style
   + native

Added: vidalia/branches/breakpad/src/vidalia/CrashReporter.h
===================================================================
--- vidalia/branches/breakpad/src/vidalia/CrashReporter.h	                        (rev 0)
+++ vidalia/branches/breakpad/src/vidalia/CrashReporter.h	2009-06-12 05:39:13 UTC (rev 3841)
@@ -0,0 +1,63 @@
+/*
+**  This file is part of Vidalia, and is subject to the license terms in the
+**  LICENSE file, found in the top level directory of this distribution. If you
+**  did not receive the LICENSE file with this file, you may obtain it from the
+**  Vidalia source package distributed by the Vidalia Project at
+**  http://www.vidalia-project.net/. No part of Vidalia, including this file,
+**  may be copied, modified, propagated, or distributed except according to the
+**  terms described in the LICENSE file.
+*/
+
+/*
+** \file CrashReporter.h
+** \version $Id$
+** \brief General routines to install a Breakpad-based exception handler and
+** set options related to launching the crash reporting application.
+*/
+
+#ifndef _CRASHREPORTER_H
+#define _CRASHREPORTER_H
+
+class QString;
+class QStringList;
+
+
+namespace CrashReporter
+{
+  /** Defines the maximum length of the absolute path plus filename of the
+   * crash reporting executable displayed when the exception handler is
+   * called.
+   */
+#if defined(Q_OS_WIN32)
+  static const int MAX_PATH_LEN = MAX_PATH;
+#else
+  static const int MAX_PATH_LEN = 4096;
+#endif
+
+  /** Installs the Breakpad exception handler and sets the static global
+   * variables used by the exception handler to launch the crash reporting
+   * application. Minidumps will be writen to <b>dumpPath</b>, which will
+   * be created if it doesn't already exist.
+   * \sa remove_exception_handler()
+   */
+  bool install_exception_handler(const QString &dumpPath);
+
+ /** Removes the application's exception handler previously created by
+  * install_exception_handler(). If no exception handler was previously created,
+  * no action will be taken.
+  * \sa install_exception_handler()
+  */
+  void remove_exception_handler();
+
+  /** Sets <b>crashReporter</b> as the executable that gets called when the
+   * exception handler catches a crash. If <b>crashReporter</b> contains one
+   * or more spaces, the given path will be wrapped in quotes. The caller is
+   * responsible for ensuring that <b>crashReporter</b> is no greater than
+   * CrashReporter::MAX_PATH_LEN (including added quotes). Returns true if
+   * the crash reporting application was set successfully, or false if
+   * <b>crashReporter</b> was too long.
+   */
+  bool set_crash_reporter(const QString &crashReporter);
+};
+
+#endif


Property changes on: vidalia/branches/breakpad/src/vidalia/CrashReporter.h
___________________________________________________________________
Added: svn:keywords
   + Id
Added: svn:eol-style
   + native

Modified: vidalia/branches/breakpad/src/vidalia/main.cpp
===================================================================
--- vidalia/branches/breakpad/src/vidalia/main.cpp	2009-06-11 17:57:53 UTC (rev 3840)
+++ vidalia/branches/breakpad/src/vidalia/main.cpp	2009-06-12 05:39:13 UTC (rev 3841)
@@ -18,6 +18,9 @@
 #include "Vidalia.h"
 #include "MainWindow.h"
 #include "VMessageBox.h"
+#if defined(USE_BREAKPAD)
+#include "CrashReporter.h"
+#endif
 
 #include "procutil.h"
 #include "stringutil.h"
@@ -29,139 +32,43 @@
 #endif
 
 #if defined(USE_BREAKPAD)
-#include <QFileInfo>
-#include <QDir>
-
+void
+setup_crash_reporter()
+{
+  /* Set the crash reporting application used to submit minidumps. On Windows,
+   * crashreporter.exe is assumed to live in the same directory as vidalia.exe.
+   */
 #if defined(Q_OS_WIN32)
-#include <client/windows/handler/exception_handler.h>
+  QString crashReporter = Vidalia::applicationDirPath() + "\\crashreporter.exe";
 #elif defined(Q_OS_MAC)
-#include <client/mac/handler/exception_handler.h>
-#elif defined(Q_OS_LINUX)
-#include <client/linux/handler/exception_handler.h>
-#elif defined(Q_OS_SOLARIS)
-#include <client/solaris/handler/exception_handler.h>
+  QString crashReporter = Vidalia::applicationDirPath() + "/CrashReporter.app";
 #endif
-
-/** Pointer to the Breakpad-installed exception handler called if Vidalia
- * crashes.
- */
-static google_breakpad::ExceptionHandler *_exceptionHandler = 0;
-
-/** If true, the crash reporting application will be displayed when the
- * Breakpad-installed exception handler is called. Otherwise, the system
- * will handle the exception itself.
- */
-static bool _showCrashReporter = true;
-
-/** Defines the maximum length of the absolute path plus filename of the
- * crash reporting executable displayed when the exception handler is
- * called.
- */
-#define MAX_PATH_LEN  4096
-
-/** Absolute path of the crash reporting application that will be launched
- * from the exception handler.
- * \sa setup_exception_handler()
- */
-static wchar_t _crashReporterAppPath[MAX_PATH_LEN + 1] = L"";
-
-
-/** Breakpad-installed exception handler. This function gets called in the
- * event of a crash. If _showCrashReporter is true, this will call execute
- * the crash reporting application, passing it the name and location of the
- * generated minidump, the absolute path to the (now crashed) Vidalia
- * executable, and any arguments that may be needed to restart Vidalia.
- */
-static bool
-minidump_callback(const wchar_t *dump, const wchar_t *id, void *context,
-#if defined(Q_OS_WIN32)
-                  EXCEPTION_POINTERS *exInfo,
-                  MDRawAssertionInfo *assertionInfo,
-#endif
-                  bool succeeded)
-{
-  if (! succeeded || ! _showCrashReporter)
-    return false;
-
-  /* Launch the crash reporter with the name and location of the minidump */
-
-  return true;
-}
-
-/** Installs the Breakpad exception handler and sets the static global
- * variables used by the exception handler to launch the crash reporting
- * application. Minidumps will be writen to <b>dumpPath</b>, which will
- * be created if it doesn't already exist.
- * \sa remove_exception_handler()
- */
-bool
-install_exception_handler(const QString &dumpPath)
-{
-  /* Create a directory for the crash dumps if it doesn't already exist */
-  QDir dumpDir(dumpPath);
-  if (! dumpDir.exists() && ! dumpDir.mkdir(".")) {
-    vWarn("Unable to create crash report directory: %1")
-                            .arg(dumpDir.absolutePath());
-    return false;
+  if (! QFileInfo(crashReporter).isExecutable()) {
+    vWarn("Unable to find crash reporting application. Crash reporting will "
+          "be unavailable.");
+    return;
   }
-  vInfo("Storing crash reports in \"%1\"").arg(dumpDir.absolutePath());
-
-
-#if defined(Q_OS_WIN32)
-  /* Set the location of the crash reporting application that will get
-   * launched if Vidalia crashes. On Windows, it is assumed to exist in the
-   * same directory as Vidalia.exe. */
-  QString crashReporterApp = vApp->applicationDirPath() + "/crashreporter.exe";
-  if (QFileInfo(crashReporterApp).isExecutable()
-        && crashReporterApp.length() <= MAX_PATH_LEN) {
-    crashReporterApp.toWCharArray(_crashReporterAppPath);
-    _crashReporterAppPath[crashReporterApp.length()] = L'\0';
-    _showCrashReporter = true;
-    vInfo("Found crash reporting application at \"%1\"").arg(crashReporterApp);
+  if (! CrashReporter::set_crash_reporter(crashReporter)) {
+    vWarn("Vidalia found the crash reporting application, but the path is "
+          "longer than your platform supports. Skipping crash reporting.");
+    return;
   }
-#else
-  /* XXX: No crash reporter support available on non-Windows yet. */
-  _showCrashReporter = false;
-#endif
 
-  /* Create the exception handler and specify where the dumps should go */
-  _exceptionHandler = new google_breakpad::ExceptionHandler(
-                            dumpDir.absolutePath().toStdWString(),
-                            NULL,
-                            minidump_callback,
-                            NULL,
-#if defined(Q_OS_WIN32)
-                            google_breakpad::ExceptionHandler::HANDLER_ALL);
-#else
-                            true);
-#endif
-  if (! _exceptionHandler) {
-    vWarn("Failed to create Breakpad exception handler. Crash reporting will "
-          "be unavailable.");
-    return true;
+  /* Install the exception handler and give it the location to which Breakpad
+   * should write its minidumps. */
+  QString dumpPath = Vidalia::dataDirectory() + "/crashreports";
+  if (! CrashReporter::install_exception_handler(dumpPath)) {
+    vWarn("Unable to setup Breakpad exception handler. Crash reporting "
+          "will be unavailable.");
+  } else {
+    vInfo("Installed Breakpad exception handler.");
   }
-  vInfo("Successfully installed Breakpad exception handler.");
-  return true;
 }
-
-/** Removes the application's exception handler previously created by
- * install_exception_handler(). If no exception handler was previously created,
- * no action will be taken.
- * \sa install_exception_handler()
- */
-void
-remove_exception_handler()
-{
-  if (_exceptionHandler) {
-    delete _exceptionHandler;
-    _exceptionHandler = 0;
-  }
-}
 #endif
 
 /** Returns true if there is already another Vidalia process running. */
 bool
-is_vidalia_running(QString pidfile)
+is_vidalia_running(const QString &pidfile)
 {
   /* Read the pidfile and find out if that process still exists */
   qint64 pid = read_pidfile(pidfile);
@@ -196,11 +103,8 @@
                                    .arg(QT_VERSION_STR);
 
 #if defined(USE_BREAKPAD)
-  /* Set the location for crash dumps if we're built with Breakpad */
-  if (! install_exception_handler(vidalia.dataDirectory() + "/crashreports")) {
-    vWarn("Unable to setup Breakpad exception handler. Crash reporting "
-          "will be unavailable.");
-  }
+  /* Set up the crash reporting application and exception handlers. */
+  setup_crash_reporter();
 #endif
 #if defined(USE_MARBLE) && defined(Q_OS_WIN32)
   vApp->addLibraryPath(vApp->applicationDirPath() + "/plugins/qt");
@@ -264,7 +168,7 @@
 
 #if defined(USE_BREAKPAD)
   vInfo("Removing Breakpad exception handler.");
-  remove_exception_handler();
+  CrashReporter::remove_exception_handler();
 #endif
 
   return ret;