问题
I am receiving a bug report with the following stack trace and I have no idea what the problem is. I've seen suggestions that this could be caused by having an emitter's image in a texture atlas or by removing an emitter in the same run loop as it is added but I don't think either of these is happening. It's a sporadic issue and I can't recreate it. I only see it in bug reports. I would love any help.
0 libsystem_platform.dylib OSSpinLockLock + 1
1 SpriteKit SKSpinLockSync(int*, void ()() block_pointer) + 92
2 SpriteKit -[SKTexture loadImageData] + 300
3 SpriteKit -[SKTexture size] + 42
4 SpriteKit SKCEmitterSprite::update(double) + 3136
5 SpriteKit SKCSprite::update(double) + 354
6 SpriteKit SKCSprite::update(double) + 354
7 SpriteKit -[SKScene _update:] + 174
8 SpriteKit -[SKView(Private) _update:] + 324
9 SpriteKit -[SKView renderCallback:] + 820
10 SpriteKit __29-[SKView setUpRenderCallback]_block_invoke + 130
11 SpriteKit -[SKDisplayLink _callbackForNextFrame:] + 254
12 QuartzCore CA::Display::DisplayLinkItem::dispatch() + 98
13 QuartzCore CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) + 344
14 IOMobileFramebuffer IOMobileFramebufferVsyncNotifyFunc + 104
15 IOKit IODispatchCalloutFromCFMessage + 248
16 ... CoreFoundation __CFMachPortPerform + 136
17 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 34
18 CoreFoundation __CFRunLoopDoSource1 + 346
19 CoreFoundation __CFRunLoopRun + 1406
20 CoreFoundation CFRunLoopRunSpecific + 524
21 CoreFoundation CFRunLoopRunInMode + 106
22 GraphicsServices GSEventRunModal + 138
23 UIKit UIApplicationMain + 1136
24 myApplication main.m line 16 main
EDIT: I'm now realizing that I get the SKSpinLockSync problem in a few different situations and not always with the emitters. I think that the only reason that I see it so often with the emitter is because that is the lions share of the image loading in the app so it's just the statistically most likely. The top four lines of the stack trace are always the same. So, up to and including [SKTexture Size]
.
回答1:
I had the same problem and I found that when I call
NSString *p = [[NSBundle mainBundle] pathForResource:name ofType:@"sks"];
SKEmitterNode *e = [NSKeyedUnarchiver unarchiveObjectWithFile:p];
many times, it will randomly crash the app with the same crash log
SKSpinLockSync(int*, void ()() block_pointer) + 36
-[SKTexture loadImageData] + 252
-[SKTexture size] + 44
SKCEmitterSprite::update(double) + 2928
I think this is Sprite Kit problem and hope Apple will fix this soon
My solution is : don't call unarchiveObjectWithFile everytime
unarchiveObjectWithFile may relate to IO and this may crash if you do that too often like every frame in your game, or the problem come from SKTexture cache system has problem when it need texture data and call loadImageData in non-thread safe.
So I reuse SKEmitterNode with copy, here is my function
// Emitter Pool
- (SKEmitterNode*)getEmitter:(NSString*)name {
if(!mDictEmitter)
self.mDictEmitter = [NSMutableDictionary new];
SKEmitterNode *e = [mDictEmitter objectForKey:name];
if(!e){
NSString *p = [[NSBundle mainBundle] pathForResource:name ofType:@"sks"];
e = [NSKeyedUnarchiver unarchiveObjectWithFile:p];
[mDictEmitter setObject:e forKey:name];
}
return [e copy];
}
回答2:
OSSpinLock is a mechanism to ensure atomic operations in multithreaded apps.
I don't think there's a multithreading issue here, but rather loadImageData may have provided data that crashes during the atomic part of the work. This could be due to a missing (or corrupt or unsupported file format) texture in the bundle. It is certainly an emitter that causes the texture load to fail.
Try testing your app in release configuration (edit the scheme) for a while. Some bugs only surface in release builds with optimizations enabled. You could also build an adhoc version of your app and deploy it to your device and test it. Your first goal right now should be to verify the issue on your own device, otherwise it may be hard to pin down.
The call stack does give you a few hints: the problem is with a emitter that is a child of a sprite which is a child of another sprite which is a child of the scene. Perhaps that narrows it down.
回答3:
I experienced the same crash in a similar case and was able to resolve it
In my case, I was attempting to play back an image sequence via an SKAction:
[SKAction animateWithTextures: timePerFrame:]
I'm unsure what the cause was, but my hunch is it has to do with textures not being preloaded. The documentation for the method does not offer any insight as to whether or not they must be preloaded so it's purely conjecture, but from what I gather SpriteKit seems to be choking because it could not load the images up fast enough to display them.
in any case, using [SKTexture preloadTextures:...
resolves my crash completely
hope it helps you and others too!
回答4:
I had a similar problem in making a game using SpriteKit. All postings to be able to be obtained from internet search was void to the solution. Sometimes, a special action type would cause this problem, not by corrupt or missing texture in the bundle if the action contains a concept of multithreading. And I did solve it! In other words, indirectly your code might have a kind of multi-threading even though there seems none of apparent multi-threads.
回答5:
I had this exact problem (same crash log stack) with particles in Sprite Kit. I tried many things over many hours -- and finally figured it out, sorta: it seemed to be because the source texture was in a Texture Atlas folder, and it didn't have the corresponding @2x image. Try moving the texture out of the texture atlas and/or adding an @2x version of the image.
回答6:
If using SKEmitterNode
and create more than 1 at the same time (close around the same time), my game still crashed. I had to manually preload (create and add emitter to scene), by then I was able to prevent the crashing I had to let the particle effect to be created and added to the scene and let it run its action. I then set the particle alpha to 0, to hide it. By then I was By Disappointment, I preloaded everything.
Using SKEmitterNode
and getEmitter
method above, I still getting crashes when I create more than 1 emitter around the same time. I solve this by creating one of the particle on the start, add it to the scene, and set its alpha
to 0. This is a jacky way and it blows, but it works and doesn't crash.
Example:
@implementation MyGameScene
- (instancetype)initWithSize:(CGSize)size
{
if(self = [super initWithSize:size]){
HitEmitter *emitter = [HitEmitter particle]; // class method use getEmitter method
[self addChild:emitter];
[emitter setName:@"temp"];
[emitter setAlpha:0];
// add a second timer to remove it.
[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(removeEmitter) userInfo:nil repeats:NO];
} return self;
}
回答7:
I am building a Spritekit app. The app crashed irregularly with no debug info only leaving a pointer to the dreaded SKSpinLockLock. The app crashed in the middle of a complex set of "animation" actions. Like R.Randazzo mentioned in his post, lazy image loading could cause these problems. But all my animations are using preloaded images. Eventually I discovered a lazy loading image "hiding in the shadow", waiting to be presented as the result of my animation sequence and user interaction. After preloading this image too, the SKSpinLockLock ghost was gone. N.B. I am developing for IOS 7 +
来源:https://stackoverflow.com/questions/19449163/what-is-skspinlocksync-in-sprite-kit-and-how-do-i-fix-it