1*9712c20fSFrederick Mayle// Copyright 2006 Google LLC 2*9712c20fSFrederick Mayle// 3*9712c20fSFrederick Mayle// Redistribution and use in source and binary forms, with or without 4*9712c20fSFrederick Mayle// modification, are permitted provided that the following conditions are 5*9712c20fSFrederick Mayle// met: 6*9712c20fSFrederick Mayle// 7*9712c20fSFrederick Mayle// * Redistributions of source code must retain the above copyright 8*9712c20fSFrederick Mayle// notice, this list of conditions and the following disclaimer. 9*9712c20fSFrederick Mayle// * Redistributions in binary form must reproduce the above 10*9712c20fSFrederick Mayle// copyright notice, this list of conditions and the following disclaimer 11*9712c20fSFrederick Mayle// in the documentation and/or other materials provided with the 12*9712c20fSFrederick Mayle// distribution. 13*9712c20fSFrederick Mayle// * Neither the name of Google LLC nor the names of its 14*9712c20fSFrederick Mayle// contributors may be used to endorse or promote products derived from 15*9712c20fSFrederick Mayle// this software without specific prior written permission. 16*9712c20fSFrederick Mayle// 17*9712c20fSFrederick Mayle// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18*9712c20fSFrederick Mayle// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19*9712c20fSFrederick Mayle// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20*9712c20fSFrederick Mayle// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21*9712c20fSFrederick Mayle// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22*9712c20fSFrederick Mayle// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23*9712c20fSFrederick Mayle// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24*9712c20fSFrederick Mayle// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25*9712c20fSFrederick Mayle// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26*9712c20fSFrederick Mayle// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27*9712c20fSFrederick Mayle// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*9712c20fSFrederick Mayle 29*9712c20fSFrederick Mayle#import <Breakpad/Breakpad.h> 30*9712c20fSFrederick Mayle 31*9712c20fSFrederick Mayle#import "Controller.h" 32*9712c20fSFrederick Mayle#import "TestClass.h" 33*9712c20fSFrederick Mayle#import "GTMDefines.h" 34*9712c20fSFrederick Mayle#include <unistd.h> 35*9712c20fSFrederick Mayle#include <mach/mach.h> 36*9712c20fSFrederick Mayle 37*9712c20fSFrederick Mayle@implementation Controller 38*9712c20fSFrederick Mayle 39*9712c20fSFrederick Mayle- (void)causeCrash { 40*9712c20fSFrederick Mayle float *aPtr = nil; 41*9712c20fSFrederick Mayle NSLog(@"Crash!"); 42*9712c20fSFrederick Mayle NSLog(@"Bad programmer: %f", *aPtr); 43*9712c20fSFrederick Mayle} 44*9712c20fSFrederick Mayle 45*9712c20fSFrederick Mayle- (void)generateReportWithoutCrash:(id)sender { 46*9712c20fSFrederick Mayle BreakpadGenerateAndSendReport(breakpad_); 47*9712c20fSFrederick Mayle} 48*9712c20fSFrederick Mayle 49*9712c20fSFrederick Mayle- (IBAction)showForkTestWindow:(id) sender { 50*9712c20fSFrederick Mayle [forkTestOptions_ setIsVisible:YES]; 51*9712c20fSFrederick Mayle} 52*9712c20fSFrederick Mayle 53*9712c20fSFrederick Mayle- (IBAction)forkTestOptions:(id)sender { 54*9712c20fSFrederick Mayle NSInteger tag = [[sender selectedCell] tag]; 55*9712c20fSFrederick Mayle NSLog(@"sender tag: %d", tag); 56*9712c20fSFrederick Mayle if (tag <= 2) { 57*9712c20fSFrederick Mayle bpForkOption = tag; 58*9712c20fSFrederick Mayle } 59*9712c20fSFrederick Mayle 60*9712c20fSFrederick Mayle if (tag == 3) { 61*9712c20fSFrederick Mayle useVFork = NO; 62*9712c20fSFrederick Mayle } 63*9712c20fSFrederick Mayle 64*9712c20fSFrederick Mayle if (tag == 4) { 65*9712c20fSFrederick Mayle useVFork = YES; 66*9712c20fSFrederick Mayle } 67*9712c20fSFrederick Mayle 68*9712c20fSFrederick Mayle if (tag >= 5 && tag <= 7) { 69*9712c20fSFrederick Mayle progCrashPoint = tag; 70*9712c20fSFrederick Mayle } 71*9712c20fSFrederick Mayle 72*9712c20fSFrederick Mayle} 73*9712c20fSFrederick Mayle 74*9712c20fSFrederick Mayle- (IBAction)forkTestGo:(id)sender { 75*9712c20fSFrederick Mayle 76*9712c20fSFrederick Mayle NSString *resourcePath = [[NSBundle bundleForClass: 77*9712c20fSFrederick Mayle [self class]] resourcePath]; 78*9712c20fSFrederick Mayle NSString *execProgname = nil; 79*9712c20fSFrederick Mayle if (progCrashPoint == DURINGLAUNCH) { 80*9712c20fSFrederick Mayle execProgname = [resourcePath stringByAppendingString:@"/crashduringload"]; 81*9712c20fSFrederick Mayle } else if (progCrashPoint == AFTERLAUNCH) { 82*9712c20fSFrederick Mayle execProgname = [resourcePath stringByAppendingString:@"/crashInMain"]; 83*9712c20fSFrederick Mayle } 84*9712c20fSFrederick Mayle 85*9712c20fSFrederick Mayle const char *progName = NULL; 86*9712c20fSFrederick Mayle if (progCrashPoint != BETWEENFORKEXEC) { 87*9712c20fSFrederick Mayle progName = [execProgname UTF8String]; 88*9712c20fSFrederick Mayle } 89*9712c20fSFrederick Mayle 90*9712c20fSFrederick Mayle int pid; 91*9712c20fSFrederick Mayle 92*9712c20fSFrederick Mayle if (bpForkOption == UNINSTALL) { 93*9712c20fSFrederick Mayle BreakpadRelease(breakpad_); 94*9712c20fSFrederick Mayle } 95*9712c20fSFrederick Mayle 96*9712c20fSFrederick Mayle if (useVFork) { 97*9712c20fSFrederick Mayle pid = vfork(); 98*9712c20fSFrederick Mayle } else { 99*9712c20fSFrederick Mayle pid = fork(); 100*9712c20fSFrederick Mayle } 101*9712c20fSFrederick Mayle 102*9712c20fSFrederick Mayle if (pid == 0) { 103*9712c20fSFrederick Mayle sleep(3); 104*9712c20fSFrederick Mayle NSLog(@"Child continuing"); 105*9712c20fSFrederick Mayle FILE *fd = fopen("/tmp/childlog.txt","wt"); 106*9712c20fSFrederick Mayle kern_return_t kr; 107*9712c20fSFrederick Mayle if (bpForkOption == RESETEXCEPTIONPORT) { 108*9712c20fSFrederick Mayle kr = task_set_exception_ports(mach_task_self(), 109*9712c20fSFrederick Mayle EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | 110*9712c20fSFrederick Mayle EXC_MASK_ARITHMETIC | EXC_MASK_BREAKPOINT, 111*9712c20fSFrederick Mayle MACH_PORT_NULL, 112*9712c20fSFrederick Mayle EXCEPTION_DEFAULT, 113*9712c20fSFrederick Mayle THREAD_STATE_NONE); 114*9712c20fSFrederick Mayle fprintf(fd,"task_set_exception_ports returned %d\n", kr); 115*9712c20fSFrederick Mayle } 116*9712c20fSFrederick Mayle 117*9712c20fSFrederick Mayle if (progCrashPoint == BETWEENFORKEXEC) { 118*9712c20fSFrederick Mayle fprintf(fd,"crashing post-fork\n"); 119*9712c20fSFrederick Mayle int *a = NULL; 120*9712c20fSFrederick Mayle printf("%d\n",*a++); 121*9712c20fSFrederick Mayle } 122*9712c20fSFrederick Mayle 123*9712c20fSFrederick Mayle fprintf(fd,"about to call exec with %s\n", progName); 124*9712c20fSFrederick Mayle fclose(fd); 125*9712c20fSFrederick Mayle int i = execl(progName, progName, NULL); 126*9712c20fSFrederick Mayle fprintf(fd, "exec returned! %d\n", i); 127*9712c20fSFrederick Mayle fclose(fd); 128*9712c20fSFrederick Mayle } 129*9712c20fSFrederick Mayle} 130*9712c20fSFrederick Mayle 131*9712c20fSFrederick Mayle- (IBAction)crash:(id)sender { 132*9712c20fSFrederick Mayle NSInteger tag = [sender tag]; 133*9712c20fSFrederick Mayle 134*9712c20fSFrederick Mayle if (tag == 1) { 135*9712c20fSFrederick Mayle [NSObject cancelPreviousPerformRequestsWithTarget:self]; 136*9712c20fSFrederick Mayle [self performSelector:@selector(causeCrash) withObject:nil afterDelay:10.0]; 137*9712c20fSFrederick Mayle [sender setState:NSOnState]; 138*9712c20fSFrederick Mayle return; 139*9712c20fSFrederick Mayle } 140*9712c20fSFrederick Mayle 141*9712c20fSFrederick Mayle if (tag == 2 && breakpad_) { 142*9712c20fSFrederick Mayle BreakpadRelease(breakpad_); 143*9712c20fSFrederick Mayle breakpad_ = NULL; 144*9712c20fSFrederick Mayle return; 145*9712c20fSFrederick Mayle } 146*9712c20fSFrederick Mayle 147*9712c20fSFrederick Mayle [self causeCrash]; 148*9712c20fSFrederick Mayle} 149*9712c20fSFrederick Mayle 150*9712c20fSFrederick Mayle- (void)anotherThread { 151*9712c20fSFrederick Mayle NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 152*9712c20fSFrederick Mayle TestClass *tc = [[TestClass alloc] init]; 153*9712c20fSFrederick Mayle 154*9712c20fSFrederick Mayle [tc wait]; 155*9712c20fSFrederick Mayle 156*9712c20fSFrederick Mayle [pool release]; 157*9712c20fSFrederick Mayle} 158*9712c20fSFrederick Mayle 159*9712c20fSFrederick Mayle- (void)awakeFromNib { 160*9712c20fSFrederick Mayle NSBundle *bundle = [NSBundle mainBundle]; 161*9712c20fSFrederick Mayle NSDictionary *info = [bundle infoDictionary]; 162*9712c20fSFrederick Mayle 163*9712c20fSFrederick Mayle 164*9712c20fSFrederick Mayle breakpad_ = BreakpadCreate(info); 165*9712c20fSFrederick Mayle 166*9712c20fSFrederick Mayle // Do some unit tests with keys 167*9712c20fSFrederick Mayle // first a series of bogus values 168*9712c20fSFrederick Mayle BreakpadSetKeyValue(breakpad_, nil, @"bad2"); 169*9712c20fSFrederick Mayle BreakpadSetKeyValue(nil, @"bad3", @"bad3"); 170*9712c20fSFrederick Mayle 171*9712c20fSFrederick Mayle // Now some good ones 172*9712c20fSFrederick Mayle BreakpadSetKeyValue(breakpad_,@"key1", @"value1"); 173*9712c20fSFrederick Mayle BreakpadSetKeyValue(breakpad_,@"key2", @"value2"); 174*9712c20fSFrederick Mayle BreakpadSetKeyValue(breakpad_,@"key3", @"value3"); 175*9712c20fSFrederick Mayle 176*9712c20fSFrederick Mayle // Look for a bogus one that we didn't try to set 177*9712c20fSFrederick Mayle NSString *test = BreakpadKeyValue(breakpad_, @"bad4"); 178*9712c20fSFrederick Mayle if (test) { 179*9712c20fSFrederick Mayle NSLog(@"Bad BreakpadKeyValue (bad4)"); 180*9712c20fSFrederick Mayle } 181*9712c20fSFrederick Mayle 182*9712c20fSFrederick Mayle // Look for a bogus one we did try to set 183*9712c20fSFrederick Mayle test = BreakpadKeyValue(breakpad_, @"bad1"); 184*9712c20fSFrederick Mayle if (test) { 185*9712c20fSFrederick Mayle NSLog(@"Bad BreakpadKeyValue (bad1)"); 186*9712c20fSFrederick Mayle } 187*9712c20fSFrederick Mayle 188*9712c20fSFrederick Mayle // Test some bad args for BreakpadKeyValue 189*9712c20fSFrederick Mayle test = BreakpadKeyValue(nil, @"bad5"); 190*9712c20fSFrederick Mayle if (test) { 191*9712c20fSFrederick Mayle NSLog(@"Bad BreakpadKeyValue (bad5)"); 192*9712c20fSFrederick Mayle } 193*9712c20fSFrederick Mayle 194*9712c20fSFrederick Mayle test = BreakpadKeyValue(breakpad_, nil); 195*9712c20fSFrederick Mayle if (test) { 196*9712c20fSFrederick Mayle NSLog(@"Bad BreakpadKeyValue (nil)"); 197*9712c20fSFrederick Mayle } 198*9712c20fSFrederick Mayle 199*9712c20fSFrederick Mayle // Find some we did set 200*9712c20fSFrederick Mayle test = BreakpadKeyValue(breakpad_, @"key1"); 201*9712c20fSFrederick Mayle if (![test isEqualToString:@"value1"]) { 202*9712c20fSFrederick Mayle NSLog(@"Can't find BreakpadKeyValue (key1)"); 203*9712c20fSFrederick Mayle } 204*9712c20fSFrederick Mayle test = BreakpadKeyValue(breakpad_, @"key2"); 205*9712c20fSFrederick Mayle if (![test isEqualToString:@"value2"]) { 206*9712c20fSFrederick Mayle NSLog(@"Can't find BreakpadKeyValue (key2)"); 207*9712c20fSFrederick Mayle } 208*9712c20fSFrederick Mayle test = BreakpadKeyValue(breakpad_, @"key3"); 209*9712c20fSFrederick Mayle if (![test isEqualToString:@"value3"]) { 210*9712c20fSFrederick Mayle NSLog(@"Can't find BreakpadKeyValue (key3)"); 211*9712c20fSFrederick Mayle } 212*9712c20fSFrederick Mayle 213*9712c20fSFrederick Mayle // Bad args for BreakpadRemoveKeyValue 214*9712c20fSFrederick Mayle BreakpadRemoveKeyValue(nil, @"bad6"); 215*9712c20fSFrederick Mayle BreakpadRemoveKeyValue(breakpad_, nil); 216*9712c20fSFrederick Mayle 217*9712c20fSFrederick Mayle // Remove one that is valid 218*9712c20fSFrederick Mayle BreakpadRemoveKeyValue(breakpad_, @"key3"); 219*9712c20fSFrederick Mayle 220*9712c20fSFrederick Mayle // Try and find it 221*9712c20fSFrederick Mayle test = BreakpadKeyValue(breakpad_, @"key3"); 222*9712c20fSFrederick Mayle if (test) { 223*9712c20fSFrederick Mayle NSLog(@"Shouldn't find BreakpadKeyValue (key3)"); 224*9712c20fSFrederick Mayle } 225*9712c20fSFrederick Mayle 226*9712c20fSFrederick Mayle // Try and remove it again 227*9712c20fSFrederick Mayle BreakpadRemoveKeyValue(breakpad_, @"key3"); 228*9712c20fSFrederick Mayle 229*9712c20fSFrederick Mayle // Try removal by setting to nil 230*9712c20fSFrederick Mayle BreakpadSetKeyValue(breakpad_,@"key2", nil); 231*9712c20fSFrederick Mayle // Try and find it 232*9712c20fSFrederick Mayle test = BreakpadKeyValue(breakpad_, @"key2"); 233*9712c20fSFrederick Mayle if (test) { 234*9712c20fSFrederick Mayle NSLog(@"Shouldn't find BreakpadKeyValue (key2)"); 235*9712c20fSFrederick Mayle } 236*9712c20fSFrederick Mayle 237*9712c20fSFrederick Mayle BreakpadAddUploadParameter(breakpad_, 238*9712c20fSFrederick Mayle @"MeaningOfLife", 239*9712c20fSFrederick Mayle @"42"); 240*9712c20fSFrederick Mayle [NSThread detachNewThreadSelector:@selector(anotherThread) 241*9712c20fSFrederick Mayle toTarget:self withObject:nil]; 242*9712c20fSFrederick Mayle 243*9712c20fSFrederick Mayle NSUserDefaults *args = [NSUserDefaults standardUserDefaults]; 244*9712c20fSFrederick Mayle 245*9712c20fSFrederick Mayle // If the user specified autocrash on the command line, toggle 246*9712c20fSFrederick Mayle // Breakpad to not confirm and crash immediately. This is for 247*9712c20fSFrederick Mayle // automated testing. 248*9712c20fSFrederick Mayle if ([args boolForKey:@"autocrash"]) { 249*9712c20fSFrederick Mayle BreakpadSetKeyValue(breakpad_, 250*9712c20fSFrederick Mayle @BREAKPAD_SKIP_CONFIRM, 251*9712c20fSFrederick Mayle @"YES"); 252*9712c20fSFrederick Mayle [self causeCrash]; 253*9712c20fSFrederick Mayle } 254*9712c20fSFrederick Mayle 255*9712c20fSFrederick Mayle progCrashPoint = DURINGLAUNCH; 256*9712c20fSFrederick Mayle [window_ center]; 257*9712c20fSFrederick Mayle [window_ makeKeyAndOrderFront:self]; 258*9712c20fSFrederick Mayle} 259*9712c20fSFrederick Mayle 260*9712c20fSFrederick Mayle@end 261