forked from orta/tumblrclient
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMMICrashReporterBridge.m
200 lines (150 loc) · 5.53 KB
/
MMICrashReporterBridge.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
//
// untitled.m
// MMICrashReporter
//
// Created by Martin Redington on 17/05/2006.
// Copyright 2006 MildMannered Industries. All rights reserved.
//
#import "MMICrashReporterBridge.h"
#import <signal.h>
// Defines. These are all duplicates of entries in mmicr_defines.h
// They are duplicated, so that the Bridge can be distributed
// as simply as possible.
#define OPEN_CRASH_REPORT_DESC_TYPE 'MIcr'
#define OPEN_BUG_REPORT_DESC_TYPE 'MIbr'
#define PASS_THRU_PARAMS_DESC_TYPE 'prdt'
#define MMI_CRASH_REPORTER_NAME @"MMICrashReporter"
#define APP_EXTENSION @"app"
#define MMI_CRASH_REPORTER_CONFIG @"MMICrashReporter"
#define MMI_CRASH_REPORTER_CONFIG_EXTENSION @"crashreporterconfig"
#define MMI_INFO_PLIST_DELIVERY_ADDRESS_KEY @"MMICrashReporterDeliveryAddress"
// This is used to store the location of the crash reporter.
static NSString *crashReporterPath = nil;
#define NUMBER_OF_SIGNALS_TO_HANDLE 19
static int SIGNALS_TO_HANDLE[] = {
SIGHUP,
SIGINT,
SIGILL,
// SIGQUIT,
SIGTRAP,
SIGABRT,
SIGEMT,
SIGFPE,
SIGKILL,
SIGBUS,
SIGSEGV,
SIGSYS,
SIGPIPE,
SIGALRM,
SIGTERM,
// SIGURG,
// SIGSTOP,
// SIGTSTP,
// SIGCONT,
// SIGCHLD,
SIGTTIN,
SIGTTOU,
// SIGIO,
SIGXCPU,
SIGXFSZ,
SIGVTALRM,
// SIGPROF,
// SIGWINCH,
// SIGINFO,
// SIGUSR1,
// SIGUSR2,
};
/**
* This actually open the app ...
*/
void mmicr_launch_crashreporter(DescType descType){
NSURL *url = [NSURL fileURLWithPath:crashReporterPath];
OSStatus status;
AEDesc recordDesc;
AEInitializeDesc(&recordDesc);
status = AECreateDesc(descType, NULL, 0, &recordDesc);
// We check the status here
if(status != noErr){
NSLog(@"MMICrashReporterBridge could not launch MMICrashReporter: Apple Event could not be created");
}
LSLaunchURLSpec inLaunchSpec;
inLaunchSpec.appURL = (CFURLRef) url;
inLaunchSpec.itemURLs = NULL;
inLaunchSpec.passThruParams = &recordDesc;
inLaunchSpec.launchFlags = kLSLaunchDontAddToRecents | kLSLaunchDefaults;
inLaunchSpec.asyncRefCon = NULL;
CFURLRef *outLaunchedURL = NULL;
status = LSOpenFromURLSpec (&inLaunchSpec, outLaunchedURL);
if(status != noErr){
NSLog(@"MMICrashReporterBridge could not launch MMICrashReporter: %d", status);
}
else{
NSLog(@"MMICrashReporterBridge launched MMICrashReporter");
}
}
////////////////////////////////////////////////////////
/**
* This is the signal handler.
*/
void mmicr_handle_signal(int signal){
NSLog(@"MMICrashReporterBridge received signal %d", signal);
NSLog(@"MMICrashReporterBridge launching CrashReporter from %@", crashReporterPath);
mmicr_launch_crashreporter(OPEN_CRASH_REPORT_DESC_TYPE);
NSLog(@"MMICrashReporterBridge terminating application");
// [NSApp terminate:nil];
exit(0);
}
////////////////////////////////////////////////////////
@implementation MMICrashReporterBridge
////////////////////////////////////////////////////////
+ (void) reportBug
{
mmicr_launch_crashreporter(OPEN_BUG_REPORT_DESC_TYPE);
}
////////////////////////////////////////////////////////
- (IBAction) reportBug:(id)sender{
[[self class] reportBug];
}
////////////////////////////////////////////////////////
+ (BOOL) installSignalHandlers
{
NSLog(@"Installing MMICrashReporterBridge signal handlers");
// work out which directory the parent app is in
NSString *mainBundlePath = [[NSBundle mainBundle] bundlePath];
// locate MMICrashReporter
if(mainBundlePath == nil){
// we are not being run from a bundle ... bail
NSLog(@"WARNING: MMICrashReporterBridge signal handlers were not installed, because:");
NSLog(@"[[NSBundle mainBundle] bundlePath] returned nil");
NSLog(@"MMICrashReporter can only currently be used with Bundle based applications");
return NO;
}
// Work out the path to MMICrashReporter.app, and make sure its there
crashReporterPath = [[NSBundle mainBundle] pathForResource:MMI_CRASH_REPORTER_NAME ofType:APP_EXTENSION];
if(crashReporterPath == nil){
NSLog(@"WARNING: MMICrashReporterBridge signal handlers were not installed, because:");
NSLog(@"%@.%@ could not be found inside the bundle's Resources directory", MMI_CRASH_REPORTER_NAME, APP_EXTENSION);
return NO;
}
// Also, are we configured ...
NSString *crashReporterConfigFilePath = [[NSBundle mainBundle] pathForResource:MMI_CRASH_REPORTER_CONFIG ofType:MMI_CRASH_REPORTER_CONFIG_EXTENSION];
if(crashReporterConfigFilePath == nil){
// We don't have a config file. Do we have an Info.plist entry for delivery ...
NSString *deliveryAddress = [[NSBundle mainBundle] objectForInfoDictionaryKey:MMI_INFO_PLIST_DELIVERY_ADDRESS_KEY];
if(deliveryAddress == nil){
NSLog(@"WARNING: MMICrashReporterBridge signal handlers were not installed, because:");
NSLog(@"Configuration could not be found in %@.%@, or in Info.plist", MMI_CRASH_REPORTER_CONFIG, MMI_CRASH_REPORTER_CONFIG_EXTENSION);
return NO;
}
}
// We're all set ...
// NSLog(@"MMICrashReporterBridge caching CrashReporter path: %@", crashReporterPath);
[crashReporterPath retain];
int i;
for(i = 0; i < NUMBER_OF_SIGNALS_TO_HANDLE; i++){
signal(SIGNALS_TO_HANDLE[i], &mmicr_handle_signal);
}
// NSLog(@"MMICrashReporterBridge Signal handlers installed");
return YES;
}
@end