A ramble on iOS crash collection framework

Source: Internet
Author: User
Tags posix

A ramble on iOS crash collection framework

In order to be able to discover the program problem in the first time, the application needs to implement its own crash log collection service, many mature open source projects, such as Kscrash,plcrashreporter,crashkit. The pursuit of convenience, for the confidentiality requirements of the procedure is not high, can also choose a variety of one-stop crash statistical products, such as Crashlytics,hockeyapp, friends, bugly and so on.

    • Is the more integrated crash Log collection service more insured?
    • I collect the crash log and the system generated by the crash log there is disagreement, who should believe?
    • Why is there a large number of crash logs showing up in the main function, but not a single line of code in the function stack?
    • The crash of the wild pointer class is difficult to locate, what is the best response?

To explain these problems, we must start with the Mach anomaly.

Mach Anomalies and UNIX signals

The iOS system comes with Apple's Crash Reporter recorded Crash logs in the device, and the Exception type entry typically contains two elements: Mach anomaly and UNIX signal.

Exception Type:         EXC_BAD_ACCESS (SIGSEGV)Exception Subtype: KERN_INVALID_ADDRESS at 0x041a6f3

What is Mach anomaly? How does it relate to the UNIX signal? Mach is a xnu core, and the Mach exception refers to the bottom-most kernel-level exception, defined <mach/exception_types.h> below. Each thread,task,host has an array of anomalous ports, and some of Mach's APIs are exposed to the user state, and the user-state developer can set Thread,task,host's exception port directly through the Mach API to catch Mach anomalies and fetch crash events.

All Mach exceptions are converted to the corresponding UNIX signal at the host layer ux_exception , and the threadsignal signal is posted to the wrong thread. The POSIX API in iOS is implemented through the BSD layer above Mach.

Therefore, the EXC_BAD_ACCESS (SIGSEGV) meaning of the expression is: the exc_bad_access of the Mach layer is abnormal, the host layer is converted to SIGSEGV signal delivery to the wrong thread. Now that the signal is finally delivered to the wrong thread, you can capture the signal by registering the Signalhandler:

signal(SIGSEGV,signalHandler);

Catching Mach anomalies or UNIX signals can catch the crash event, which is better in both ways? The Mach exception is preferred because Mach exception handling occurs before the UNIX signal processing, and if the handler of the Mach exception causes the program to exit, then the UNIX signal will never reach this process. The conversion of UNIX signals is intended to be compatible with the more popular POSIX standard (SUS specification), so it is not necessary to understand that the Mach kernel can also be developed in a way that is compatible with UNIX signaling.

Because the hardware-generated signals (via CPU traps) are captured by the Mach layer before being converted to the corresponding UNIX signals; Apple's system and user-generated signals (via calls kill and pthread_kill ) are first sunk to Mach anomalies and then to UNIX signals for the purpose of unifying the mechanism.

The realization idea of crash collection

As mentioned above, the crash event can be captured by capturing the Mach anomaly, or the UNIX signal, so that a total of 3 scenarios are summed up.

1) Mach anomaly mode 2) UNIX signaling mode
signal(SIGSEGV,signalHandler);
3) Mach Abnormal +unix signal mode

In this way, most open-source projects on GitHub, even in the case of a preferred catch Mach exception, discard the capture Exc_crash exception and choose to capture the corresponding SIGABRT signal. The famous open source project, Plcrashreporter, gives a detailed explanation in the code comments:

We still need to use signal handlers to catch SIGABRT in-process. The kernel sends an EXC_CRASH Mach exception to denote sigabrt termination. In this case, catching the Mach exception in-process leads to process deadlock in an uninterruptable wait. Thus, we fall back on the BSD signal handlers for SIGABRT, and don't register for EXC_CRASH .

In addition, it is important to note that special handling is also required for application-level exception nsexception. Have you ever seen a crash in the crash log of the main function, but there is no code for you in the function stack:

Thread0Crashed:0Libsystem_kernel.Dylib0x3a61757c__semwait_signal_nocancel+0x181Libsystem_c.Dylib0x3a592a7cNanosleep$Nocancel+0xa02Libsystem_c.Dylib0x3a5adedeUsleep$Nocancel+0x2e3Libsystem_c.Dylib0x3a5c7fe0Abort+0x504libc++Abi.Dylib0x398f6cd2Abort_message+0x465libc++Abi.Dylib0x3990f6e0Default_terminate_handler()+0xf86Libobjc.A.Dylib0x3a054f62_objc_terminate()+0xBE7libc++Abi.Dylib0x3990d1c4Std::__terminate(void(*)())+0x4c8libc++Abi.Dylib0x3990cd28__cxa_rethrow+0x609Libobjc.A.Dylib0x3a054e12Objc_exception_rethrow+0x2610Corefoundation0x2f7d7f30Cfrunlooprunspecific+0x27c11 corefoundation 0x2f7d7c9e cfrunloopruninmode + 0x6612 graphicsservices  0x346dd65e gseventrunmodal + 0x8613 uikit 0x32124148 uiapplicationmain + 0x46c14 xxxxxx 0x0003b1f2 main + 0x1f215 libdyld. Dylib 0X3A561AB4 start + 0x0    

It can be seen that a nsexception cause the program to crash, only to get this nsexception, get it, the reason name callStackSymbols information to determine the problem of the program location.

/* NSException Class Reference */@property(ReadOnly,Copy) nsstring *name; @property  (readonlycopy) nsstring *reason; @property  (readonlycopy) nsarray *callstacksymbols; @property  (readonlycopy) nsarray *callstackreturnaddresses     

The method is simple and can be registered to NSUncaughtExceptionHandler catch exception information:

static void my_uncaught_exception_handler (NSException *exception) { //这里可以取到 NSException 信息}NSSetUncaughtExceptionHandler(&my_uncaught_exception_handler);

Write the nsexception details to the crash log, pinpoint the error location of the program:

Application Specific Information:*** Terminating app due to uncaught exception ‘NSUnknownKeyException‘, reason: ‘[<__NSDictionaryI 0x14554d00> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key key.‘Last Exception Backtrace:0 CoreFoundation 0x2f8a3f7e     __exceptionPreprocess + 0x7e1 libobjc.A.dylib 0x3a054cc     objc_exception_throw + 0x222 CoreFoundation 0x2f8a3c94     -[NSException raise] + 0x43 Foundation 0x301e8f1e         -[NSObject(NSKeyValueCoding) setValue:forKey:] + 0xc64 DemoCrash 0x00085306          -[ViewController crashMethod] + 0x6e5 DemoCrash 0x00084ecc          main + 0x1cc6 DemoCrash 0x00084cf8          start + 0x24

So, is not received a large number of crash in the main function but no nsexception information of the log, on behalf of their own integrated crash log collection service is not registered Nsuncaughtexceptionhandler it? Not necessarily, there is another possibility, is the simultaneous existence of other crash log collection service to the pit.

A pit where multiple crash log collection services coexist

Yes, it's not a smart idea to integrate multiple crash log collection services into your own programs. Typically, the third-party functionality SDK integrates a crash collection service to discover the problems of its SDK in a timely manner. When the services are to ensure that their crash statistics are correct and complete for the purpose, it is inevitable that the sequence of hands and feet, forced coverage and so on the malicious competition, there will always be someone silently by the pit.

1) refusal to pass Uncaughtexceptionhandler

If there are multiple parties registering the exception handler through Nssetuncaughtexceptionhandler, the peaceful practice is: After the registrant through the Nsgetuncaughtexceptionhandler will be previously registered handler out and back up, In their own handler processing after consciously put other people's handler register back, the orderly transfer. The consequence of not passing a forced override is that the crash log written by the log collection service that was previously registered will be lost due to the loss of NSException Last Exception Backtrace . (P.S. iOS system comes with crash reporter not affected)

In the development test phase, you can use the Fishhook framework to hook NSSetUncaughtExceptionHandler method, so you can clearly see the handler transfer process where the fault, quickly locate the polluting environment. It is not recommended to use the debugger to add symbolic breakpoints to check because some crash collection frameworks are not working in debug state.

Sample Instrumentation code:

StaticNsuncaughtexceptionhandler*G_vailduncaughtexceptionhandler;Staticvoid(*Ori_nssetuncaughtexceptionhandler)(Nsuncaughtexceptionhandler*);voidMy_nssetuncaughtexceptionhandler(Nsuncaughtexceptionhandler*Handler){G_vailduncaughtexceptionhandler=Nsgetuncaughtexceptionhandler();If(G_vailduncaughtexceptionhandler!=Null){nslog (@ "uncaughtexceptionhandler=%p" ,g_vailduncaughtexceptionhandler); } ori_nssetuncaughtexceptionhandler (handler< Span class= "P" >); nslog (@ "%@" ,[nsthread callstacksymbolsg_vailduncaughtexceptionhandler = nsgetuncaughtexceptionhandler< Span class= "P" > (); nslog (@ "uncaughtexceptionhandler=%p"  g_vailduncaughtexceptionhandler);                /span>               

For jailbreak plug-in application process inside, malicious coverage nssetuncaughtexceptionhandler situation, the application itself is relatively vulnerable to processing, because the jailbreak environment operation timing of the play more than the right relatively large.

2) Mach abnormal port swap out + signal processing handler coverage

Similar to Nssetuncaughtexceptionhandler, the set of Mach anomalous ports and signal handlers can also be eliminated, resulting in the inability to capture crash events.

3) Impact system crash log accuracy

The more services the application tier participates in collecting crash logs, the more likely it will affect the crash Reporter that comes with the iOS system. Due to the changes in the process inline array, it may cause the system log thread Crashed label dislocation, can search abort() and other keywords to review the system log accuracy. If the program due to NSException and crash, the information in the system log Last Exception Backtrace is complete and accurate, will not be affected by the application layer of nonsense, can be used as a reference to troubleshoot problems.

The crash of OBJC wild pointer class

Collect crash log This step without problems, or there are many full system stack of the situation, without their own line of code, analysis is very tricky, OBJC wild pointer class crash is so, here are recommended a few Good articles:

    • How to locate obj-c field pointer random Crash (a): increase the crash rate of the wild hands first
    • How to locate the Obj-c field pointer random Crash (ii): Make the non-mandatory crash into a must-present
    • How to locate the Obj-c field pointer random Crash (iii): Add Black technology let crash tell
    • Tips for analyzing crashes at Objc_msgsend ()

In addition, some additional information can be added to the crash log to assist in positioning, such as cutting marks thread origin, queue origin, recording user operation trajectory, etc...

A ramble on iOS crash collection framework

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.