Include obj-c exception info in crash reports.
b=451709 r=ted r=bent sr=roc
--- a/toolkit/crashreporter/mac_utils.h
+++ b/toolkit/crashreporter/mac_utils.h
@@ -33,15 +33,20 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef toolkit_breakpad_mac_utils_h__
#define toolkit_breakpad_mac_utils_h__
+#include "nsStringGlue.h"
+
/*
* Look up a setting in our user defaults indicating
* that the user wants to see the OS crash reporting dialog.
*/
bool PassToOSCrashReporter();
+// Given an Objective-C NSException object, put exception info into a string.
+void GetObjCExceptionInfo(void* inException, nsACString& outString);
+
#endif /* toolkit_breakpad_mac_utils_h__ */
--- a/toolkit/crashreporter/mac_utils.mm
+++ b/toolkit/crashreporter/mac_utils.mm
@@ -15,16 +15,17 @@
* The Original Code is Mozilla Breakpad integration
*
* The Initial Developer of the Original Code is
* Ted Mielczarek <ted.mielczarek@gmail.com>
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
+ * Josh Aas <josh@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
@@ -34,22 +35,55 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <Foundation/Foundation.h>
#include "mac_utils.h"
#include "nsObjCExceptions.h"
+#include "nsXPCOM.h"
bool PassToOSCrashReporter()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
BOOL osCrashReporter = [userDefaults boolForKey:@"OSCrashReporter"];
[pool release];
return osCrashReporter == YES;
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
}
+
+void GetObjCExceptionInfo(void* inException, nsACString& outString)
+{
+ NSException* e = (NSException*)inException;
+
+ NSString* name = [e name];
+ NSString* reason = [e reason];
+ unsigned int nameLength = [name length];
+ unsigned int reasonLength = [reason length];
+
+ unichar* nameBuffer = (unichar*)NS_Alloc(sizeof(unichar) * (nameLength + 1));
+ if (!nameBuffer)
+ return;
+ unichar* reasonBuffer = (unichar*)NS_Alloc(sizeof(unichar) * (reasonLength + 1));
+ if (!reasonBuffer) {
+ NS_Free(nameBuffer);
+ return;
+ }
+
+ [name getCharacters:nameBuffer];
+ [reason getCharacters:reasonBuffer];
+ nameBuffer[nameLength] = '\0';
+ reasonBuffer[reasonLength] = '\0';
+
+ outString.AssignLiteral("\nObj-C Exception data:\n");
+ AppendUTF16toUTF8(nameBuffer, outString);
+ outString.AppendLiteral(": ");
+ AppendUTF16toUTF8(reasonBuffer, outString);
+
+ NS_Free(nameBuffer);
+ NS_Free(reasonBuffer);
+}
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -15,16 +15,17 @@
* The Original Code is Mozilla Breakpad integration
*
* The Initial Developer of the Original Code is
* Ted Mielczarek <ted.mielczarek@gmail.com>
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
+ * Josh Aas <josh@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
@@ -880,9 +881,19 @@ nsresult WriteMinidumpForException(EXCEP
{
if (!gExceptionHandler)
return NS_ERROR_NOT_INITIALIZED;
return gExceptionHandler->WriteMinidumpForException(aExceptionInfo) ? NS_OK : NS_ERROR_FAILURE;
}
#endif
+#ifdef XP_MACOSX
+nsresult AppendObjCExceptionInfoToAppNotes(void *inException)
+{
+ nsCAutoString excString;
+ GetObjCExceptionInfo(inException, excString);
+ AppendAppNotesToCrashReport(excString);
+ return NS_OK;
+}
+#endif
+
} // namespace CrashReporter
--- a/toolkit/crashreporter/nsExceptionHandler.h
+++ b/toolkit/crashreporter/nsExceptionHandler.h
@@ -57,11 +57,14 @@ nsresult UnsetExceptionHandler();
nsresult AnnotateCrashReport(const nsACString& key, const nsACString& data);
nsresult AppendAppNotesToCrashReport(const nsACString& data);
nsresult SetRestartArgs(int argc, char** argv);
nsresult SetupExtraData(nsILocalFile* aAppDataDirectory,
const nsACString& aBuildID);
#ifdef XP_WIN32
nsresult WriteMinidumpForException(EXCEPTION_POINTERS* aExceptionInfo);
#endif
+#ifdef XP_MACOSX
+ nsresult AppendObjCExceptionInfoToAppNotes(void *inException);
+#endif
}
#endif /* nsExceptionHandler_h__ */
--- a/toolkit/xre/MacLaunchHelper.h
+++ b/toolkit/xre/MacLaunchHelper.h
@@ -34,17 +34,13 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __MacLaunchHelper_h__
#define __MacLaunchHelper_h__
-#ifdef __cplusplus
extern "C" {
-#endif
void LaunchChildMac(int aArgc, char** aArgv);
-#ifdef __cplusplus
}
-#endif
#endif
deleted file mode 100644
--- a/toolkit/xre/MacLaunchHelper.m
+++ /dev/null
@@ -1,96 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Communicator client code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Ben Goodger <ben@mozilla.org>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "MacLaunchHelper.h"
-
-#include "nsObjCExceptions.h"
-
-#include <Cocoa/Cocoa.h>
-
-#ifdef __ppc__
-#include <sys/types.h>
-#include <sys/sysctl.h>
-#include <mach/machine.h>
-#endif /* __ppc__ */
-
-void LaunchChildMac(int aArgc, char** aArgv)
-{
- NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
-
- int i;
- NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSTask* child = [[[NSTask alloc] init] autorelease];
- NSMutableArray* args = [[[NSMutableArray alloc] init] autorelease];
-
-#ifdef __ppc__
- // It's possible that the app is a universal binary running under Rosetta
- // translation because the user forced it to. Relaunching via NSTask would
- // launch the app natively, which the user apparently doesn't want.
- // In that case, try to preserve translation.
-
- // If the sysctl doesn't exist, it's because Rosetta doesn't exist,
- // so don't try to force translation. In case of other errors, just assume
- // that the app is native.
-
- int isNative = 0;
- size_t sz = sizeof(isNative);
-
- if (sysctlbyname("sysctl.proc_native", &isNative, &sz, NULL, 0) == 0 &&
- !isNative) {
- // Running translated on ppc.
-
- cpu_type_t preferredCPU = CPU_TYPE_POWERPC;
- sysctlbyname("sysctl.proc_exec_affinity", NULL, NULL,
- &preferredCPU, sizeof(preferredCPU));
-
- // Nothing can be done to handle failure, relaunch anyway.
- }
-#endif /* __ppc__ */
-
- for (i = 1; i < aArgc; ++i)
- [args addObject: [NSString stringWithCString: aArgv[i]]];
-
- [child setCurrentDirectoryPath:[[[NSBundle mainBundle] executablePath] stringByDeletingLastPathComponent]];
- [child setLaunchPath:[[NSBundle mainBundle] executablePath]];
- [child setArguments:args];
- [child launch];
- [pool release];
-
- NS_OBJC_END_TRY_ABORT_BLOCK;
-}
-
new file mode 100644
--- /dev/null
+++ b/toolkit/xre/MacLaunchHelper.mm
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Ben Goodger <ben@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "MacLaunchHelper.h"
+
+#include "nsObjCExceptions.h"
+
+#include <Cocoa/Cocoa.h>
+
+#ifdef __ppc__
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <mach/machine.h>
+#endif /* __ppc__ */
+
+void LaunchChildMac(int aArgc, char** aArgv)
+{
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
+
+ int i;
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSTask* child = [[[NSTask alloc] init] autorelease];
+ NSMutableArray* args = [[[NSMutableArray alloc] init] autorelease];
+
+#ifdef __ppc__
+ // It's possible that the app is a universal binary running under Rosetta
+ // translation because the user forced it to. Relaunching via NSTask would
+ // launch the app natively, which the user apparently doesn't want.
+ // In that case, try to preserve translation.
+
+ // If the sysctl doesn't exist, it's because Rosetta doesn't exist,
+ // so don't try to force translation. In case of other errors, just assume
+ // that the app is native.
+
+ int isNative = 0;
+ size_t sz = sizeof(isNative);
+
+ if (sysctlbyname("sysctl.proc_native", &isNative, &sz, NULL, 0) == 0 &&
+ !isNative) {
+ // Running translated on ppc.
+
+ cpu_type_t preferredCPU = CPU_TYPE_POWERPC;
+ sysctlbyname("sysctl.proc_exec_affinity", NULL, NULL,
+ &preferredCPU, sizeof(preferredCPU));
+
+ // Nothing can be done to handle failure, relaunch anyway.
+ }
+#endif /* __ppc__ */
+
+ for (i = 1; i < aArgc; ++i)
+ [args addObject: [NSString stringWithCString: aArgv[i]]];
+
+ [child setCurrentDirectoryPath:[[[NSBundle mainBundle] executablePath] stringByDeletingLastPathComponent]];
+ [child setLaunchPath:[[NSBundle mainBundle] executablePath]];
+ [child setArguments:args];
+ [child launch];
+ [pool release];
+
+ NS_OBJC_END_TRY_ABORT_BLOCK;
+}
--- a/toolkit/xre/Makefile.in
+++ b/toolkit/xre/Makefile.in
@@ -147,18 +147,18 @@ CPPSRCS += nsNativeAppSupportUnix.cpp
else
CPPSRCS += nsNativeAppSupportDefault.cpp
endif
endif
endif
endif
endif
-ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
-CMSRCS = MacLaunchHelper.m
+ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
+CMMSRCS += MacLaunchHelper.mm
CPPSRCS += nsCommandLineServiceMac.cpp
LOCAL_INCLUDES += -I$(topsrcdir)/xpfe/bootstrap/appleevents
OS_CXXFLAGS += -fexceptions
SHARED_LIBRARY_LIBS += $(DEPTH)/xpfe/bootstrap/appleevents/$(LIB_PREFIX)appleevents_s.$(LIB_SUFFIX)
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
CMMSRCS += MacApplicationDelegate.mm
endif
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -855,16 +855,26 @@ nsXULAppInfo::WriteMinidumpForException(
#ifdef XP_WIN32
return CrashReporter::WriteMinidumpForException(static_cast<EXCEPTION_POINTERS*>(aExceptionInfo));
#else
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
#endif
+NS_IMETHODIMP
+nsXULAppInfo::AppendObjCExceptionInfoToAppNotes(void* aException)
+{
+#ifdef XP_MACOSX
+ return CrashReporter::AppendObjCExceptionInfoToAppNotes(aException);
+#else
+ return NS_ERROR_NOT_IMPLEMENTED;
+#endif
+}
+
static const nsXULAppInfo kAppInfo;
static NS_METHOD AppInfoConstructor(nsISupports* aOuter,
REFNSIID aIID, void **aResult)
{
NS_ENSURE_NO_AGGREGATION(aOuter);
return const_cast<nsXULAppInfo*>(&kAppInfo)->
QueryInterface(aIID, aResult);
--- a/xpcom/base/nsObjCExceptions.h
+++ b/xpcom/base/nsObjCExceptions.h
@@ -41,28 +41,42 @@
#define nsObjCExceptions_h_
#import <Foundation/Foundation.h>
#ifdef DEBUG
#import <ExceptionHandling/NSExceptionHandler.h>
#endif
+#if defined(MOZ_CRASHREPORTER) && defined(__cplusplus)
+#include "nsICrashReporter.h"
+#include "nsCOMPtr.h"
+#include "nsServiceManagerUtils.h"
+#endif
+
#include <unistd.h>
#include <signal.h>
#include "nsError.h"
// See Mozilla bug 163260.
// This file can only be included in an Objective-C context.
static void nsObjCExceptionLog(NSException* aException)
{
NSLog(@"Mozilla has caught an Obj-C exception [%@: %@]",
[aException name], [aException reason]);
+#if defined(MOZ_CRASHREPORTER) && defined(__cplusplus)
+ // Attach exception info to the crash report.
+ nsCOMPtr<nsICrashReporter> crashReporter =
+ do_GetService("@mozilla.org/toolkit/crash-reporter;1");
+ if (crashReporter)
+ crashReporter->AppendObjCExceptionInfoToAppNotes(static_cast<void*>(aException));
+#endif
+
#ifdef DEBUG
@try {
// Try to get stack information out of the exception. 10.5 returns the stack
// info with the callStackReturnAddresses selector.
NSArray *stackTrace = nil;
if ([aException respondsToSelector:@selector(callStackReturnAddresses)]) {
NSArray* addresses = (NSArray*)
[aException performSelector:@selector(callStackReturnAddresses)];
--- a/xpcom/system/nsICrashReporter.idl
+++ b/xpcom/system/nsICrashReporter.idl
@@ -38,17 +38,17 @@
#include "nsISupports.idl"
/**
* Provides access to crash reporting functionality.
* @status UNSTABLE - This interface is not frozen and will probably change in
* future releases.
*/
-[scriptable, uuid(189c9392-157c-445f-84db-900eb46d4839)]
+[scriptable, uuid(D9A0F5B2-A7DF-4AEB-9775-21B9E01B4C59)]
interface nsICrashReporter : nsISupports
{
/**
* Add some extra data to be submitted with a crash report.
* @param key
* Name of the data to be added.
* @param data
* Data to be added.
@@ -74,10 +74,16 @@ interface nsICrashReporter : nsISupports
void appendAppNotesToCrashReport(in ACString data);
/**
* Write a minidump immediately, with the user-supplied exception
* information. This is implemented on Windows only, because
* SEH (structured exception handling) exists on Windows only.
* @param aExceptionInfo EXCEPTION_INFO* provided by Window's SEH
*/
- [noscript] void WriteMinidumpForException(in voidPtr aExceptionInfo);
+ [noscript] void writeMinidumpForException(in voidPtr aExceptionInfo);
+
+ /**
+ * Append note containing an Obj-C exception's info.
+ * @param aException NSException object to append note for
+ */
+ [noscript] void appendObjCExceptionInfoToAppNotes(in voidPtr aException);
};