Lots of app crashes but cannot reproduce

Hi everybody!

I’m getting lots of crash reports on my latest app (https://apps.apple.com/us/app/national-hero/id1500338790) and it’s always the same report. The problem is I don’t know what could be wrong. I don’t have any crashs in the simulator, not on my device, not on my test device and not on my wife’s device.

The app has this line of code in almost all views’ Activate handler:
Xojo.Core.Timer.CallLater(10, AddressOf m001_DelayedLayout)

In that method I’m doing this:
If Xojo.System.Version.MajorVersion >= 13 Then recMenuBackground.SetEffect(BlurStyle_MenuBackground, VibrancyStyle_MenuBackground, Nil)

Not sure if that’s the problem because I have these crash reports for iOS 12 too. But I would assume there is something happening in this method because the crash reports indicate it’s right after the timer fires. It would be extremely helpful to somehow find out if it’s always the same view that’s crashing.

This is the crash report and I would appreciate any help. Thank you!

Date/Time:           2020-10-22 21:14:18.8987 +0100
Launch Time:         2020-10-22 21:14:10.1457 +0100
OS Version:          iPhone OS 12.1.2 (16C101)
Baseband Version:    5.32.00
Report Version:      104

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

Thread 0 name:
Thread 0 Crashed:
0   libsystem_kernel.dylib        	0x00000001b8a93104 __pthread_kill + 8
1   libsystem_pthread.dylib       	0x00000001b8b0f020 pthread_kill$VARIANT$mp + 380 (pthread.c:1492)
2   libsystem_c.dylib             	0x00000001b89ead78 abort + 140 (abort.c:94)
3   libsystem_c.dylib             	0x00000001b89b867c __assert_rtn + 316 (assert.c:91)
4   Bundestrainer                 	0x00000001057cfccc UnhandledException(RuntimeObject*) + 456 (iOSApplication.mm:92)
5   Bundestrainer                 	0x00000001057e1b78 CallUserCode<RuntimeObject *, RuntimeObject *> + 36 (XojoExceptions.h:73)
6   Bundestrainer                 	0x00000001057e1b78 -[XOJTimerAdapter timerFireMethod:] + 116 (RBCoreTimer.mm:37)
7   Foundation                    	0x00000001b99b1488 __NSFireTimer + 84 (NSTimer.m:264)
8   CoreFoundation                	0x00000001b8e8d828 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 28 (CFRunLoop.c:1830)
9   CoreFoundation                	0x00000001b8e8d558 __CFRunLoopDoTimer + 864 (CFRunLoop.c:2417)
10  CoreFoundation                	0x00000001b8e8cd8c __CFRunLoopDoTimers + 248 (CFRunLoop.c:2564)
11  CoreFoundation                	0x00000001b8e87c68 __CFRunLoopRun + 1880 (CFRunLoop.c:0)
12  CoreFoundation                	0x00000001b8e871f0 CFRunLoopRunSpecific + 436 (CFRunLoop.c:3247)
13  GraphicsServices              	0x00000001bb100584 GSEventRunModal + 100 (GSEvent.c:2245)
14  UIKitCore                     	0x00000001e6092d40 UIApplicationMain + 212 (UIApplication.m:4347)
15  Bundestrainer                 	0x00000001057d0650 runIOSMainLoop() + 44 (iOSAppDelegate.mm:170)
16  Bundestrainer                 	0x00000001040e2bb8 Xojo._RuntimeRun + 36
17  Bundestrainer                 	0x00000001056baf94 _Main + 404
18  Bundestrainer                 	0x00000001056ba894 main + 36
19  libdyld.dylib                 	0x00000001b8946bb4 start + 4

Whenever you are calling this:

Xojo.Core.Timer.CallLater(10, AddressOf m001_DelayedLayout)

If it happens so that the control/class instance containing the method “m001_DelayedLayout”
is not existing anymore you’ll get a crash.

You SHOULD unregister the call in the destructor (or view close event) if you have registered the call.

If aCallWasRegistered Then    
Xojo.Core.Timer.CancelCall( AddressOf m001_DelayedLayout)
end if

Do NOT call this if the call was not added, that’s why aCallWasRegistered is used as an example.

Using WeakAddressOf instead may work, but it’s not guaranteed, since the same crashes are to be found on the forums somewhere.

Perhaps you can set the delay to “0” which means “call this method the next event loop” it could work.

1 Like

Thanks for your feedback! If I cancel the call, the code inside that method will not be executed, right? Could I potentially add it to the if-clause where I first cancel and then run it?

What could be a reason why the m001_DelayedLayout wouldn’t exist anymore? It’s a local method in each view as shown on the picture.
Bildschirmfoto 2020-10-23 um 19.22.29

Thank you again, I will try setting the delay to 0 and see what happens.

If LoadingView closes, the address of the method will be gone. Since the timer runs of a (dictionary?) that is coming from the main loop it will still try to call the method while the address is gone. That causes a crash.

Say you open the loading view then the timer is called in .Activate. Now the LoadingView closes (for whatever reason) before the timer fired,… The call is still pending, now the timer elapsed and bam, crash since it calls an address that’s non existing.

It’s better to have single shot timer on the view that’s started when the view activates, or opens then in the Run or Action event, call your function. Since that timer would be on the view, it will close with it if it’s destructed.

Got it, thanks a lot! I will try this and see if it reduces this kind of crash.

it “can” also be something inside the timer, but since you’ve shown now code… can can’t see what’s happening there? maybe declares?

Usually there are no declares. Most of the time, the method consists of a single line:
If Xojo.System.Version.MajorVersion >= 13 Then recMenuBackground.SetEffect(BlurStyle_MenuBackground, VibrancyStyle_MenuBackground, Nil)

BlurStyle_MenuBackground is = iOSRectangle.BlurStyles.ExtraLight
VibrancyStyle_MenuBackground is = iOSRectangle.VibrancyStyles.Fill

I actually believe it’s what you just said, the user is closing the view before the DelayedLayout method is being run. Cause as I said, I haven’t been able to reproduce it on any device. Just tested setting the delay to 0 but that doesn’t work. Delay = 1 works fine. I’ll keep you posted.

To try to re-produce try closing the view asap or set de delay longer and then reproduce to see if you get the same crash. 90% of the crashlog methods should remain the same.

This portion is the most important i think:

0 libsystem_kernel.dylib 0x00000001b8a93104 __pthread_kill + 8
1 libsystem_pthread.dylib 0x00000001b8b0f020 pthread_kill$VARIANT$mp + 380 (pthread.c:1492)
2 libsystem_c.dylib 0x00000001b89ead78 abort + 140 (abort.c:94)
3 libsystem_c.dylib 0x00000001b89b867c __assert_rtn + 316 (assert.c:91)
4 Bundestrainer 0x00000001057cfccc UnhandledException(RuntimeObject*) + 456 (iOSApplication.mm:92)
5 Bundestrainer 0x00000001057e1b78 CallUserCode<RuntimeObject *, RuntimeObject *> + 36 (XojoExceptions.h:73)
6 Bundestrainer 0x00000001057e1b78 -[XOJTimerAdapter timerFireMethod:] + 116 (RBCoreTimer.mm:37)
7 Foundation 0x00000001b99b1488 __NSFireTimer + 84 (NSTimer.m:264)

You see the timer is calling CallUserCode and it calls XojoExceptions.h (thus creating an exception there)
The next call after it is UnhandledException.

you can cas it back to the name of the exception (if it was a subclass):

Var exceptionType As Text = Xojo.Core.Introspection.GetType(e).FullName
/// Write to log... exceptionType ...
1 Like

I use this technique very often in my apps with one major difference. I use WeakAddressOf

In one of my apps I get an exception thrown due to the timer trying to run code in a view that isn’t available anymore. I tried to track from which View this comes from but haven’t fixed it yet.
Fortunately the user never experiences a crash because I have Return True in App.UnhandledException
The experience of an app crashing is so bad for a mobile app that I prefer the user to not know that something went wrong and just let the app continue running and not closing.

1 Like