What can cause SIGABRT on dispatch_async in iOS9.1?

I am trying to debug an error that many of my users in this area report. Everyone shows me the same stack:

Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x0000000000000000, 0x0000000000000000 Exception Note: EXC_CORPSE_NOTIFY Triggered by Thread: 8 OS Version: iOS 9.1 (13B143) Code Type: ARM (Native) 0 libsystem_kernel.dylib 0x392ccc84 0x392b8000 + 85124 1 libsystem_pthread.dylib 0x39370732 0x3936c000 + 18226 2 libsystem_c.dylib 0x39264f9a 0x3921a000 + 307098 3 libsystem_c.dylib 0x39264f2c 0x3921a000 + 306988 4 libsystem_c.dylib 0x392447ea 0x3921a000 + 174058 5 MyApp 0x000cb3e0 __69-[MyDataManager myMethod:]_block_invoke (MyDataManager.m:2367) 

Line 2367 is simple:

 2363: BOOL success = [db executeUpdate:@"INSERT INTO table (id, content) VALUES (?, ?)", message.remoteId, message.content]; 2364: assert(success); 2365: DebugLog(@"DB Results %d", success); 2366: 2367: dispatch_async(dispatch_get_main_queue(), ^{ 2368: [self cleanupMethod:args]; 2369: }); 

Although the code is defined in this block, it is only 1 line, and this code does not work on this stack, because otherwise I would see cleanupMethod above myMethod .

Edit: you can see that there is a statement before sending async! Initially, I thought this crash was caused by a statement. But the line numbers never matched - the statement was many lines higher (line 2364, not 2367) - and when I tested it further, I saw that if assert is triggered, my stack will not include _block_invoke which you can add to the end of the call myMethod.

Can anyone suggest how dispatch_async can cause this behavior? Also, is there any way for me to symbolize Apple code in libsystem_c.dylib?

Binary image libsystem_c.dylib:

 0x3921a000 - 0x3927efff libsystem_c.dylib armv7 <0b5d65608e6f38448cd207fbd748d372> /usr/lib/system/libsystem_c.dylib 

NOTE. The object in question is a global singleton, my "data manager", if you like. It handles network requests and storage states, which might need to be shared with UIViewControllers. It is initially declared as follows:

 + (MyDataManager *)mainStore { static dispatch_once_t once; static id sharedInstance; dispatch_once(&once, ^{ sharedInstance = [[self alloc] init]; }); return sharedInstance; } 

I understand the consequences of freeing an object when calling the cleanupMethod:args method ... but I thought that my global singleton would always be around and therefore always safe to call like I do in my code? Also, I don't care about saving loops, since again this should be a global single.

Is this sample code below OK?

 @interface MyDataManager @end @implementation MyDataManager + (MyDataManager *)mainStore { static dispatch_once_t once; static id sharedInstance; dispatch_once(&once, ^{ sharedInstance = [[self alloc] init]; }); return sharedInstance; } - (void)myMethod { NSDictionary *args = @{...} ... dispatch_async(dispatch_get_main_queue(), ^{ [self cleanupMethod:args]; }); } - (void)cleanupMethod:(id)args { ... } @end @interface MyViewController : UIViewController @end @implementation MyViewController - (void)viewDidLoad { [super viewDidLoad]; [[MyDataManager sharedInstance] myMethod]; } @end 
+7
ios grand-central-dispatch sigabrt dispatch-async
source share
1 answer

It seems that the problem is with self , which causes your application to crash, apparently when calling self , which was released. This code will create a new variable that will store a weak link to self , which should fix the problem:

 __weak typeof(self)weakSelf = self; dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf cleanupMethod:args]; }); 

Someone will say that you should use __strong typeof(weakSelf)strongSelf = weakSelf; here, and also, to make a strong link to a broken link, to avoid a strong reference loop, but to keep self alive, but I would prefer not to do it here and in the case of self would be nil by the time the block was executed - messages to nil fine in objective -c, so nothing will happen.

Plus a stack trace from what happens before the line

 0x000cb3e0 __69-[MyDataManager myMethod:]_block_invoke (MyDataManager.m:2367) 

will definitely help diagnose the problem.

EDIT: well, it seems you are not using the mainStore class mainStore when accessing a shared object. Perhaps this is the problem.

+2
source share

All Articles