What is SKSpinLockSync in a sprite set and how to fix it?

I get an error report with the following stack trace and I have no idea what the problem is. I have seen suggestions that this could be caused by the presence of an emitter image in the texture atlas or by removing the emitter in the same run cycle as added, but I do not think this is happening. This is a sporadic problem, and I cannot recreate it. I see this only in error reports. I would really like to 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: Now I understand that I have SKSpinLockSync problem in several different situations and not always with emitters. I think the only reason I see this with the emitter so often is because it is the share of lions in uploading images to the application, so this is just statistically most likely. The top four lines of the stack trace are always the same. So, down to the [SKTexture Size] .

+6
source share
7 answers

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 accidentally crash the application 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 a problem with the Sprite Kit and I hope that Apple will fix it soon.

My solution: do not call unarchiveObjectWithFile every time

unarchiveObjectWithFile can relate to IO, and it can crash if you do it too often, like every frame in your game, or a problem arising from the SKTexture caching system has problems when it needs texture data and causes loadImageData to be safe different from threads.

So, I am reusing SKEmitterNode with a 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]; } 
+5
source

OSSpinLock is a mechanism for providing atomic operations in multi-threaded applications.

I do not think that there is a multithreaded problem, but loadImageData can provide data that fails during the atomic part of the work. This may be due to the absence (or a damaged or unsupported file format) of the texture in the kit. This is, of course, an emitter that causes a loss of texture load.

Try to test the application in the release configuration (edit the schema) for a while. Some bugs that occur only in the release are built with optimizations enabled. You can also create an adhoc version of your application and deploy it on your device and test it. Your first goal right now should be to test the problem on your own device, otherwise it can be difficult to fix.

You will find some tips on the call stack: the problem is that the emitter is a child of the sprite, which is a child of another sprite, which is a child of the scene. Perhaps this narrows it.

+2
source

In a similar case, I encountered the same failure and was able to solve it.

In my case, I tried to reproduce a sequence of images using SKAction:

 [SKAction animateWithTextures: timePerFrame:] 

I'm not sure what the reason is, but I suspect this is due to the fact that the textures were not preloaded. The documentation for this method gives no idea whether preloading should be preloaded or not, but from what I collect, SpriteKit seems to choke because it cannot load images fast enough to display them.

anyway using [SKTexture preloadTextures:... fully resolves my failure

Hope this helps you and other people!

+2
source

I had a similar problem when creating a game using SpriteKit. All messages that can be obtained from an Internet search have been deprived of a solution. Sometimes a particular type of action causes this problem, rather than a corrupt or missing texture in the package, if the action contains the concept of multithreading. And I decided that! In other words, indirectly, your code may have a kind of multithreading, although there seem to be no visible multithreading threads.

0
source

I had this exact problem (same crash log table) with particles in a Sprite kit. I tried a lot of things for hours - and finally figured it out, sorta: it seems because the original texture was in the Texture Atlas folder and it didn't have the corresponding @ 2x image. Try moving the texture from the texture atlas and / or add the @ 2x image version.

0
source

If you use SKEmitterNode and at the same time create more than 1 (close to the same time), my game still crashed. I had to manually preload (create and add a radiator to the scene), by then I could prevent the crash, I had to allow the particle effect to be created and add it to the scene and let it trigger its action. Then I set the alpha of the particle to 0 to hide it. By then I was "Disappointed", I had preloaded everything.

Using the SKEmitterNode and getEmitter above, I still get crashes when I create more than one emitter at about the same time. I solve this by creating one of the particles at the beginning, add it to the scene and set its alpha to 0. This is the path to the hacks, and it blows, but it works and does not 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; } 
0
source

I am creating a Spritekit application. The application crashed irregularly without debugging information, leaving a pointer to the scary SKSpinLockLock. The app crashed in the middle of a complex set of "animated" actions. As R. Randazzo mentioned in his post, lazy loading of images can cause these problems. But all my animations use preloaded images. In the end, I found a lazy loading image "hiding in the shadows", awaiting presentation as a result of my sequence of animation and user interaction. After preloading this image, there was no ghost SKSpinLockLock. Notabene I'm developing for iOS 7+

-1
source

Source: https://habr.com/ru/post/956234/


All Articles