简体   繁体   中英

periodic IOS crash, but I do not see any involvement of my app in crash report

About once a week I'm getting a crash like this one. Maybe I'm wrong, but I do not see any involvement of my app ("WayAndSee"). Does anybody have a hint how to proceed?

Attached the crash report (which is very typically for that kind of crash), I just truncated the trailing list of libraries.

Many thanks in advance ...

Incident Identifier: 348BDC52-6574-4EED-A6C7-45E79E696875
CrashReporter Key:   f8ac3e1a61b8129920a4ad40aaa56d5536e2ce22
Hardware Model:      iPhone6,2
Process:             WayAndSee [8286]
Path:                /private/var/containers/Bundle/Application/F1542EC3-3708-4B6E-80EA-A2333883359E/WayAndSee.app/WayAndSee
Identifier:          Hobrink.WayAndSee
Version:             2487 (0.3.0)
Code Type:           ARM (Native)
Role:                Foreground
Parent Process:      launchd [1]
Coalition:           Hobrink.WayAndSee [2936]


Date/Time:           2017-04-04 14:28:15.3459 +0200
Launch Time:         2017-04-04 13:05:54.5835 +0200
OS Version:          iPhone OS 10.2.1 (14D27)
Report Version:      104

Exception Type:  EXC_CRASH (SIGKILL)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note:  EXC_CORPSE_NOTIFY
Termination Reason: Namespace SPRINGBOARD, Code 0x8badf00d
Triggered by Thread:  0

Filtered syslog:
None found

Thread 0 Crashed:
0   libsystem_kernel.dylib          0x1cedf84c mach_msg_trap + 20
1   CoreFoundation                  0x1d7082f9 __CFRunLoopServiceMachPort + 137
2   CoreFoundation                  0x1d7065f7 __CFRunLoopRun + 1015
3   CoreFoundation                  0x1d655533 CFRunLoopRunSpecific + 487
4   CoreFoundation                  0x1d655341 CFRunLoopRunInMode + 105
5   GraphicsServices                0x1ee2cbfd GSEventRunModal + 157
6   UIKit                           0x22863e67 -[UIApplication _run] + 575
7   UIKit                           0x2285e591 UIApplicationMain + 151
8   WayAndSee                       0x000ba890 main (AppDelegateV2a.swift:667)
9   libdyld.dylib                   0x1ce1f50b start + 3

Thread 1 name:  com.apple.uikit.eventfetch-thread
Thread 1:
0   libsystem_kernel.dylib          0x1cedf84c mach_msg_trap + 20
1   CoreFoundation                  0x1d7082f9 __CFRunLoopServiceMachPort + 137
2   CoreFoundation                  0x1d7065f7 __CFRunLoopRun + 1015
3.  CoreFoundation                  0x1d655533 CFRunLoopRunSpecific + 487
4   CoreFoundation                  0x1d655341 CFRunLoopRunInMode + 105
5   Foundation                      0x1dfaf88b -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 261
6   Foundation                      0x1dfce631 -[NSRunLoop(NSRunLoop) runUntilDate:] + 87
7   UIKit                           0x2316a2b3 -[UIEventFetcher threadMain] + 129
8   Foundation                      0x1e098b11 __NSThread__start__ + 1161
9   libsystem_pthread.dylib         0x1cfa9a27 _pthread_body + 217
10  libsystem_pthread.dylib         0x1cfa994d _pthread_start + 235
11  libsystem_pthread.dylib         0x1cfa749c thread_start + 8

Thread 2 name:  NetworkLoad
Thread 2:
0   libsystem_kernel.dylib          0x1cedf84c mach_msg_trap + 20
1   CoreFoundation                  0x1d7082f9 __CFRunLoopServiceMachPort + 137
2   CoreFoundation                  0x1d7065f7 __CFRunLoopRun + 1015
3   CoreFoundation                  0x1d655533 CFRunLoopRunSpecific + 487
4   CoreFoundation                  0x1d655341 CFRunLoopRunInMode + 105
5   GeoServices                     0x244775ff _runNetworkThread + 475
6   libsystem_pthread.dylib         0x1cfa9a27 _pthread_body + 217
7   libsystem_pthread.dylib         0x1cfa994d _pthread_start + 235
8   libsystem_pthread.dylib         0x1cfa749c thread_start + 8

Thread 3:
0   libsystem_kernel.dylib          0x1cef5744 __workq_kernreturn + 8
1   libsystem_pthread.dylib         0x1cfa7490 start_wqthread + 8

Thread 4:
0   libsystem_pthread.dylib         0x1cfa7488 start_wqthread + 0

Thread 5:
0   libsystem_pthread.dylib         0x1cfa7488 start_wqthread + 0

Thread 6:
0   libsystem_pthread.dylib         0x1cfa7488 start_wqthread + 0

Thread 0 crashed with ARM Thread State (32-bit):
    r0: 0x10004005    r1: 0x07000806      r2: 0x00000000      r3: 0x00000c00
    r4: 0x00002403    r5: 0xffffffff      r6: 0x00000000      r7: 0x0042adb4
    r8: 0x00000c00    r9: 0x00002403     r10: 0x07000806     r11: 0x00000000
    ip: 0xffffffe1    sp: 0x0042ad78      lr: 0x1cedf63f      pc: 0x1cedf84c
  cpsr: 0x60000010

Binary Images:
0xb0000 - 0x177fff WayAndSee armv7  <7506039ae577329ab9868e3122d84f5f> /var/containers/Bundle/Application/F1542EC3-3708-4B6E-80EA-A2333883359E/WayAndSee.app/WayAndSee
0x25c000 - 0x267fff libswiftCoreData.dylib armv7s  <3022e21a184d3e6c93bac1ad7b18be30> /var/containers/Bundle/Application/F1542EC3-3708-4B6E-80EA-A2333883359E/WayAndSee.app/Frameworks/libswiftCoreData.dylib
0x27c000 - 0x28bfff libswiftCoreGraphics.dylib armv7s  <4415e467b6df386591e646e7a2978da6> /var/containers/Bundle/Application/F1542EC3-3708-4B6E-80EA-A2333883359E/WayAndSee.app/Frameworks/libswiftCoreGraphics.dylib
0x2a8000 - 0x2affff libswiftCoreImage.dylib armv7s  <9bbbe5b77fdd3551921ca7ec1a98ae38> /var/containers/Bundle/Application/F1542EC3-3708-4B6E-80EA-A2333883359E/WayAndSee.app/Frameworks/libswiftCoreImage.dylib
0x2c0000 - 0x2ebfff dyld armv7s  <898b6b42ae3b3ffb8de9a96b7071f49d> /usr/lib/dyld
0x42c000 - 0x6abfff libswiftCore.dylib armv7s  <b760608c5d35390099731eedb8821bc0> /var/containers/Bundle/Application/F1542EC3-3708-4B6E-80EA-A2333883359E/WayAndSee.app/Frameworks/libswiftCore.dylib

....

as I got several questions about my progress on this issue, I decided to wrote an answer by myself. Maybe this could be helpful for others.

The crash reports has one important line: "Termination Reason: Namespace SPRINGBOARD, Code 0x8badf00d" -> the SPRINGBOARD tried to start the app in background... and "0x8dadf00d" could be read as "ate bad food" (look around here on StackOverflow, numerous explanation for that code)

The root cause of that issue is simply the launchtime. It's too long for a start in background. There is a time limit for background start of about 5 to 7 seconds. Launch in foreground has an allowed time window of about 20 sec.

This time limit includes the time BEFORE main() and AFTER main() until the app its settled and ready to receive the launching event. Each launch of an app in background is caused by a launching event (location, file transfer etc.)

To get an idea how to analyze the time before main() I suggest to watch the video "Optimizing App Startup Time", Session 406, WWDC 2016. They explain in detail what happen BEFORE main and how to analyze and measure it. They describe several environment variables (set in "arguments" section of the scheme) which produce helpful logs.

"main()", yes, I learned it during this examination. Swift allows it to have a main(). It's even a possibility to execute statements outside of a function, class, struct ... There is no real need for that in swift. But as I wanted to measure the launch time after main, I wrote this simple main.swift file to do so.

//
//  main.swift
//  ...
//
//  Created by Hartwig Hopfenzitz on 31.05.17.
//  Copyright © 2017 Hopfenzitz. All rights reserved.
//

import Foundation
import UIKit

// very first statement after load.. the current time
let WaysStartTime = CFAbsoluteTimeGetCurrent()

// build the parameters for the call to UIApplicationMain()
let argc = CommandLine.argc
let argv = UnsafeMutableRawPointer(CommandLine.unsafeArgv).bindMemory(to: UnsafeMutablePointer<Int8>.self, capacity: Int(CommandLine.argc))

// start the main loop
UIApplicationMain(argc, argv, nil, NSStringFromClass(AppDelegate.self))

As you can see: In the very first statement I take the time. With this I can measure the time difference to the time when the app is up and running.

However: If you want to use a main() in your swift project, you have to comment out or delete the statement "@UIApplicationMain" in AppDelegate.swift. This statement "simulates" the main() function, so it would be redundant.

And yes, it is worth to start measure on main(). I did also tests with time measuring starting on "willFinishLaunchingWithOptions:". On my usual test device, an iPhone 5s (real test device, not a simulator), the difference is about 0.4 sec. I'm sure that time depends on the app and how it is structured, so I suggest to measure it from main().

OK, and as always: "if you measure, you are able to manage".

The usual root cause for slow launch times is an overloaded main thread. This main thread is the most important working horse of each app. It burdens the event loop and the UI.

So my first step was to shift as much work as possible away from main threat by using GCD (Grand Central Dispatch). GCD is quite easy to use and gives you a lot of options to fine tune the workload of the several threads. There are several videos on WWDC about GCD, my personal favorite one is the "Building Responsive and Efficient Apps with GCD", Session 718, WWDC 2015.

However, by this I reduced the number of crashes drastically, BUT.... there was still crashes ...

My initial screen is so complex, using a lot of autolayout and autosizing etc.. It simply sometimes took to long to finish the rendering before the time limit crashes the app. If I understand everything right, IOS wants to have the first screen up and running, to consider a successful launch.

Well, the magic words are "the first screen".

I love my Main.storyboard, very nice looking and highly adaptive. So I didn't want to strip it down. Luckily I found this blog http://timdietrich.me/blog/swift-multiple-storyboards/ . It describes the steps necessary to work with several storyboards in an swift/xcode project. There are several others to find on the internet, but this one is quite easy to read and understand.

So I created a storyboard called "Start.storyboard". This storyboard is very simple, just a copy of the Launchscreen.storyboard. And I used this as "the first screen".

I created this class for the ViewController of this start screen, which does nothing else than launching my Main.Storyboard.

//
//  StartViewController.swift
//  ...
//
//  Created by Hartwig Hopfenzitz on 02.06.17.
//  Copyright © 2017 Hopfenzitz. All rights reserved.
//

import UIKit

class StartViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        // Create instance of our main storyboard
        let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)

        // Create the instance of main's initial view controller.
        let mainController = mainStoryboard.instantiateViewController(withIdentifier: "WaysViewController") as UIViewController

        // Make sure it will start on the main thread
        DispatchQueue.main.async(execute: {

            // present it .. and never come back
            mainController.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
            mainController.modalPresentationStyle = .fullScreen // Display on top of current UIView

            self.present(mainController, animated: true, completion: nil)
        })
    }
}

In Info.plist you will find the key "Main storyboard file base name". This key tells which story board is the one with the initial screen. So in my example you have to change the value from "Main" to "Start", as the new initial storyboard is called "Start.storyboard".

And Voilá: the first screen starts almost immediately and IOS is very happy about the launch time. The user doesn't recognize it.

OK that's how I got rid of this crashes... maybe it will help others...

Happy coding ;-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM