[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[vidalia-svn] r3839: Checkpoint my current Breakpad integration stuff, now that t (vidalia/branches/breakpad/src/vidalia)
Author: edmanm
Date: 2009-06-11 03:03:19 -0400 (Thu, 11 Jun 2009)
New Revision: 3839
Modified:
vidalia/branches/breakpad/src/vidalia/main.cpp
Log:
Checkpoint my current Breakpad integration stuff, now that the VS build issues
are out of the way.
Modified: vidalia/branches/breakpad/src/vidalia/main.cpp
===================================================================
--- vidalia/branches/breakpad/src/vidalia/main.cpp 2009-06-11 06:52:48 UTC (rev 3838)
+++ vidalia/branches/breakpad/src/vidalia/main.cpp 2009-06-11 07:03:19 UTC (rev 3839)
@@ -29,6 +29,9 @@
#endif
#if defined(USE_BREAKPAD)
+#include <QFileInfo>
+#include <QDir>
+
#if defined(Q_OS_WIN32)
#include <client/windows/handler/exception_handler.h>
#elif defined(Q_OS_MAC)
@@ -39,11 +42,36 @@
#include <client/solaris/handler/exception_handler.h>
#endif
-static google_breakpad::ExceptionHandler *gExceptionHandler = 0;
-#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;
-#if defined(USE_BREAKPAD)
+/** 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)
@@ -52,28 +80,85 @@
#endif
bool succeeded)
{
- return succeeded;
+ if (! succeeded || ! _showCrashReporter)
+ return false;
+
+ /* Launch the crash reporter with the name and location of the minidump */
+
+ return true;
}
-#endif
-void
-set_exception_handler(const QString &dumpPath)
+/** 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)
{
-#if defined(USE_BREAKPAD)
- /* XXX: Convert dumpPath to a wchar_t* and pass it to the handler */
- Q_UNUSED(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;
+ }
+ vInfo("Storing crash reports in \"%1\"").arg(dumpDir.absolutePath());
- gExceptionHandler = new google_breakpad::ExceptionHandler(
- L".",
+
+#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);
+ }
+#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
- Q_UNUSED(dumpPath);
+ true);
#endif
+ if (! _exceptionHandler) {
+ vWarn("Failed to create Breakpad exception handler. Crash reporting will "
+ "be unavailable.");
+ return true;
+ }
+ 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)
@@ -110,9 +195,13 @@
vNotice("Vidalia %1 using Qt %2").arg(Vidalia::version())
.arg(QT_VERSION_STR);
+#if defined(USE_BREAKPAD)
/* Set the location for crash dumps if we're built with Breakpad */
- set_exception_handler(Vidalia::dataDirectory());
-
+ if (! install_exception_handler(vidalia.dataDirectory() + "/crashreports")) {
+ vWarn("Unable to setup Breakpad exception handler. Crash reporting "
+ "will be unavailable.");
+ }
+#endif
#if defined(USE_MARBLE) && defined(Q_OS_WIN32)
vApp->addLibraryPath(vApp->applicationDirPath() + "/plugins/qt");
#endif
@@ -172,6 +261,12 @@
/* Vidalia exited, so cleanup our pidfile and return */
QFile::remove(pidfile);
vNotice("Vidalia is exiting cleanly (return code %1).").arg(ret);
+
+#if defined(USE_BREAKPAD)
+ vInfo("Removing Breakpad exception handler.");
+ remove_exception_handler();
+#endif
+
return ret;
}