I have an iOS app that consistently crashes when you try to delete a GKTurnBasedMatch using

[match removeWithCompletionHandler:^(NSError *error){}];

When the completion handler is called, error is nil, meaning that it successfully deleted the match. The match does get deleted (it never re-appears), but at the same time, gamed (the background daemon written by apple that communicates with GameCenter servers) crashes.

Here is what I see in the Console when I delete a game:

Jan 19 20:47:22 Ben-L-iPhone gamed[2233] <Error>: *** Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault for '0xd000000000b4002a <x-coredata://C0390AE6-6CD0-4A7C-B080-B7649175419A/TurnBasedSession/p45>''
    *** First throw call stack:
    (0x185ce309c 0x191c61d78 0x1859eb7ac 0x1859fc50c 0x1859fc47c 0x185a7475c 0x185a79034 0x185a797f4 0x185a7a474 0x1922303e0 0x192235d88 0x185a6f3e4 0x185a7a104 0x1859fdbd0 0x100099284 0x185a71b6c 0x1922303e0 0x192235f2c 0x185a71d00 0x10009ce08 0x1000ba8a4 0x192230420 0x1922303e0 0x192235930 0x1922303e0 0x1922373fc 0x192237638 0x1923c5918 0x1923c57a8)
Jan 19 20:47:22 Ben-L-iPhone ReportCrash[2509] <Notice>: ReportCrash acting against PID 2233
Jan 19 20:47:22 Ben-L-iPhone ReportCrash[2509] <Notice>: Formulating crash report for process gamed[2233]
Jan 19 20:47:22 Ben-L-iPhone com.apple.launchd[1] (com.apple.gamed[2233]) <Warning>: (com.apple.gamed) Job appears to have crashed: Abort trap: 6
Jan 19 20:47:22 Ben-L-iPhone ReportCrash[2509] <Notice>: Saved crashreport to /var/mobile/Library/Logs/CrashReporter/gamed_2014-01-19-204722_Ben-L-iPhone.plist using uid: 0 gid: 0, synthetic_euid: 501 egid: 0

Any ideas what could trigger this? I've searched the Apple Dev forums and Google and haven't been able to find someone with a similar problem.

Crash Report Logged

Incident Identifier: C201F189-7311-49E5-96F4-890A65FAA19A
CrashReporter Key:   0b745533f4a51b30bf9654557be6c063d06f1ccc
Hardware Model:      iPhone6,1
Process:             gamed [2233]
Path:                /usr/libexec/gamed
Identifier:          gamed
Version:             ???
Code Type:           ARM-64 (Native)
Parent Process:      launchd [1]

Date/Time:           2014-01-19 20:47:22.522 -0600
OS Version:          iOS 7.0.4 (11B554a)
Report Version:      104

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Triggered by Thread:  11

Last Exception Backtrace:
0   CoreFoundation                  0x185ce309c __exceptionPreprocess + 132
1   libobjc.A.dylib                 0x191c61d78 objc_exception_throw + 60
2   CoreData                        0x1859eb7ac _PFFaultHandlerLookupRow + 1900
3   CoreData                        0x1859fc50c -[NSManagedObject(_NSInternalMethods) _newPropertiesForRetainedTypes:andCopiedTypes:preserveFaults:] + 108
4   CoreData                        0x1859fc47c -[NSManagedObject(_NSInternalMethods) _newAllPropertiesWithRelationshipFaultsIntact__] + 108
5   CoreData                        0x185a7475c -[NSManagedObjectContext(_NSInternalAdditions) _committedSnapshotForObject:] + 72
6   CoreData                        0x185a79034 -[NSManagedObjectContext(_NestedContextSupport) _copyChildObject:toParentObject:fromChildContext:] + 144
7   CoreData                        0x185a797f4 -[NSManagedObjectContext(_NestedContextSupport) _parentProcessSaveRequest:inContext:error:] + 1092
8   CoreData                        0x185a7a474 __82-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]_block_invoke + 660
9   libdispatch.dylib               0x1922303e0 _dispatch_client_callout + 16
10  libdispatch.dylib               0x192235d88 _dispatch_barrier_sync_f_slow + 352
11  CoreData                        0x185a6f3e4 _perform + 124
12  CoreData                        0x185a7a104 -[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:] + 184
13  CoreData                        0x1859fdbd0 -[NSManagedObjectContext save:] + 840
14  gamed                           0x100099284 0x100048000 + 332420
15  CoreData                        0x185a71b6c developerSubmittedBlockToNSManagedObjectContextPerform + 100
16  libdispatch.dylib               0x1922303e0 _dispatch_client_callout + 16
17  libdispatch.dylib               0x192235f2c _dispatch_barrier_sync_f_invoke + 48
18  CoreData                        0x185a71d00 -[NSManagedObjectContext performBlockAndWait:] + 132
19  gamed                           0x10009ce08 0x100048000 + 347656
20  gamed                           0x1000ba8a4 0x100048000 + 469156
21  libdispatch.dylib               0x192230420 _dispatch_call_block_and_release + 24
22  libdispatch.dylib               0x1922303e0 _dispatch_client_callout + 16
23  libdispatch.dylib               0x192235930 _dispatch_async_redirect_invoke + 152
24  libdispatch.dylib               0x1922303e0 _dispatch_client_callout + 16
25  libdispatch.dylib               0x1922373fc _dispatch_root_queue_drain + 400
26  libdispatch.dylib               0x192237638 _dispatch_worker_thread2 + 76
27  libsystem_pthread.dylib         0x1923c5918 _pthread_wqthread + 356
28  libsystem_pthread.dylib         0x1923c57a8 start_wqthread + 4

Additional Information I went back and added logging around the removeMatch. This logging is from the sandbox, but it happens in production too.

Notice, the game is already in a final state (status:GKTurnBasedMatchStatusEnded) right before the match is removed.

As soon as I removed the match, I tried to start a new match. The first try results in a "The operation couldn’t be completed. (Cocoa error 4097.)", the second try nearly 2 minutes later results in a GKServerStatusCode=5000 because the player is no longer authenticated.

2014-01-19 22:23:31.436 KingChase[3432:70b] removing match <GKTurnBasedMatch 0xc50d8f0 - matchID:e0e24a77-fb5c-46a7-b843-21e8becf9735 bundleID:us.pojo.kingchase status:GKTurnBasedMatchStatusEnded message:'Game Over! kctest2 won.' creationDate:2014-01-20 04:17:31 +0000 currentParticipant:(null) participants:<GKTurnBasedParticipant 0xc4e9870 - playerID:G:1972295489 (local player) status:Done matchOutcome:Won lastTurnDate:2014-01-20 04:22:50 +0000 timeoutDate:(null)>,<GKTurnBasedParticipant 0xc439aa0 - playerID:G:1972168157 status:Done matchOutcome:Lost lastTurnDate:2014-01-20 04:23:17 +0000 timeoutDate:(null)> matchData.length:438 matchDataMaximumSize:65536 exchanges:(null)>
2014-01-19 22:23:31.441 KingChase[3432:70b] Match removed.
2014-01-19 22:23:31.442 KingChase[3432:70b] Match cleaned up.
2014-01-19 22:23:40.681 KingChase[3432:70b] Match Making failed. Error Domain=NSCocoaErrorDomain Code=4097 "The operation couldn’t be completed. (Cocoa error 4097.)"
2014-01-19 22:25:30.053 KingChase[3432:70b] Match Making failed. Error Domain=GKErrorDomain Code=6 "The requested operation could not be completed because local player has not been authenticated." UserInfo=0xc527430 {GKServerStatusCode=5000, NSUnderlyingError=0xc5222b0 "The operation couldn’t be completed. status = 5000, missing required header: x-gk-player-id", NSLocalizedDescription=The requested operation could not be completed because local player has not been authenticated.}

The other player was able to delete the game without crashing gamed.

Updated Jan 20, 2014 - 6:32PM CDT - Further Information

I have added logging with every single interaction that I make with GameKit.

Jan 20 17:39:17 Ben-L-iPhone KingChase[3154] <Warning>: GK: [match.currentParticipant.playerID isEqualToString:localPlayer.playerID]
Jan 20 17:39:17 Ben-L-iPhone KingChase[3154] <Warning>: GK: [match participantQuitOutOfTurnWithOutcome:GKTurnBasedMatchOutcomeQuit withCompletionHandler:completionHandler];
Jan 20 17:39:18 Ben-L-iPhone KingChase[3154] <Warning>: removing match <GKTurnBasedMatch 0x1669bdb0 - matchID:a182e163-8006-413e-a203-c93d534ac550 bundleID:us.pojo.kingchase status:GKTurnBasedMatchStatusEnded message:'Game Over! kctest1 won.' creationDate:2014-01-20 23:12:32 +0000 currentParticipant:(null) participants:<GKTurnBasedParticipant 0x166ae6f0 - playerID:G:1972168157 (local player) status:Done matchOutcome:Won lastTurnDate:2014-01-20 23:27:14 +0000 timeoutDate:(null)>,<GKTurnBasedParticipant 0x1664d260 - playerID:G:1972295489 status:Done matchOutcome:Lost lastTurnDate:2014-01-20 23:38:15 +0000 timeoutDate:(null)> matchData.length:390 matchDataMaximumSize:65536 exchanges:(null)>
Jan 20 17:39:18 Ben-L-iPhone KingChase[3154] <Warning>: GK: [match removeWithCompletionHandler:^(NSError *error)
Jan 20 17:39:18 Ben-L-iPhone KingChase[3154] <Warning>: Match removed.
Jan 20 17:39:18 Ben-L-iPhone KingChase[3154] <Warning>: Match cleaned up.
Jan 20 17:39:19 Ben-L-iPhone gamed[3125] <Error>: *** Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault for '0xd00000000024001a <x-coredata://3A4F66E1-B95C-4692-B905-EA1398FB97CE/TurnBasedSession/p9>''
    *** First throw call stack:
    (0x185ce309c 0x191c61d78 0x1859eb7ac 0x1859fc50c 0x1859fc47c 0x185a7475c 0x185a79034 0x185a797f4 0x185a7a474 0x1922303e0 0x192235d88 0x185a6f3e4 0x185a7a104 0x1859fdbd0 0x10014d284 0x185a71b6c 0x1922303e0 0x192235f2c 0x185a71d00 0x100150e08 0x10016e8a4 0x192230420 0x1922303e0 0x192235930 0x1922303e0 0x1922373fc 0x192237638 0x1923c5918 0x1923c57a8)

I think this now has to do with my calling

[match participantQuitOutOfTurnWithOutcome:GKTurnBasedMatchOutcomeQuit withCompletionHandler:completionHandler];

after the game is already complete. I will test the hypothesis when I have time and submit the bug report to Apple.

有帮助吗?

解决方案

I have figured out that this problem appears to happen when you call [match removeWithCompletionHandler:^(NSError *error)] from within the completion handler of another GameKit call.

If you look in the log above:

[match participantQuitOutOfTurnWithOutcome:GKTurnBasedMatchOutcomeQuit withCompletionHandler:completionHandler];

is called, and the completionHandler for that method was calling -removeWithCompletionHandler:

I solved this problem using this change:

by executing the removeWithCompletionHandler in this manner:

[match performSelector:@selector(removeWithCompletionHandler:) withObject:^(NSError *error) {} afterDelay:5.0];
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top