Crashes occur on iOS 26.4

Since updating the OS to 26.4, the app has been crashing more often after I launch it.

The devices on which this issue has been confirmed are as follows: ・iPhone SE (2nd generation) ・9th-generation iPad ・8th-generation iPad ・5th-generation iPad mini

We have confirmed that the application functions properly on all devices prior to the OS update.

Additional information The app was developed using Unity. After contacting Unity, they indicated that based on the crash logs, it is highly likely that a “Segmentation Fault” occurred. I suspect the “Segmentation Fault” is caused by insufficient memory, but is it possible that memory usage has increased significantly in iOS 26.4 compared to previous OS versions?

Since updating the OS to 26.4, the app has been crashing more often after I launch it.

Please post the full crash log, using the instructions found here.

Additional information: The app was developed using Unity. After contacting Unity, they indicated that based on the crash logs, it is highly likely that a “Segmentation Fault” occurred.

A "Segmentation Fault" just means your app attempted to access invalid memory, which doesn't actually tell you very much about why you actually crashed. The document "Diagnosing memory, thread, and crash issues early" has a good overview of the tools that can help file this sort of issue, followed by some specific examples of what can cause this kind of failure.

I suspect the “Segmentation Fault” is caused by insufficient memory.

No, not really. Memory exceptions (what a seg fault is) happen because you’re accessing memory that you either never allocated or have already freed, neither of which will happen due to direct lack of memory. Keep in mind that your app can't really "run out" of memory in the way you're describing. Your app allocates address space by calling "malloc" and uses real memory when it actually stores data into address space it's allocated. If/when physical memory becomes limited, the system eventually responds by killing your app. That's very different from a segmentation fault.

but is it possible that memory usage has increased significantly in iOS 26.4 compared to previous OS versions?

No, not really.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Thank you for your reply. I have attached the log file. I apologize for the inconvenience, but please take a look.

Part 1:

Thank you for your reply. I have attached the log file. I apologize for the inconvenience, but please take a look.

So, starting with the log, the first thing that jumps out at me is that it's ascribing the crash to this stack in thread 0:

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread:
0   libsystem_kernel.dylib        	       0x24a42ccd4 mach_msg2_trap + 8
1   libsystem_kernel.dylib        	       0x24a43030c mach_msg2_internal + 76 
2   libsystem_kernel.dylib        	       0x24a43022c mach_msg2 + 4  [inlined]
3   libsystem_kernel.dylib        	       0x24a43022c mach_msg_overwrite + 424 
4   libsystem_kernel.dylib        	       0x24a430078 mach_msg + 24 
5   CoreFoundation                	       0x19b9dfea4 __CFRunLoopServiceMachPort + 160 
6   CoreFoundation                	       0x19b9a9f94 __CFRunLoopRun + 1188 
7   CoreFoundation                	       0x19b9a91d0 _CFRunLoopRunSpecificWithOptions + 532 
8   GraphicsServices              	       0x240eb7498 GSEventRunModal + 120 
9   UIKitCore                     	       0x1a166d2cc -[UIApplication _run] + 796 
10  UIKitCore                     	       0x1a15d8158 UIApplicationMain + 332 
11  UnityFramework                	       0x11cbfbb08
12  sekai                         	       0x1020bbbb8
13  dyld                          	       0x1985bdc1c start + 6928

That's basically "wrong", or at least deeply misleading. mach_msg2_trap is one of a number of functions that operate as final entry points into the kernel. As such, they aren't really something your app is "running" as much as they are places where your app is waiting to hear "back" from the kernel. Similarly, functions like this are SO heavily used [1] by the entire system that essentially ANY bug/failure in their basic implementation is basically catastrophic.

[1] The "mach_msg2*" stack above is a VERY strong contender for THE most frequently called function in the entire system. On a typical machine, I'd guess that its call rate is EASILY in the "billions/day", if not "trillions/day”.

Because of that, in practice, you'll either:

  • Crash in one of the earlier functions leading "into" them (because something was "wrong" with your input).

OR

  • Crash in one of the earlier functions returning "from" them (because your app didn't like whatever the kernel returned to you).

...but you'll basically "never" crash inside them. Looking at your other thread, the rest of them (with one exception) are all blocked in functions I'd put in a similar category:

0   libsystem_kernel.dylib        	       0x24a42cc50 semaphore_wait_trap + 8
...
0   libsystem_kernel.dylib        	       0x24a4325e8 __psynch_cvwait + 8
...
0   libsystem_kernel.dylib        	       0x24a432808 __semwait_signal + 8
...
0   libsystem_kernel.dylib        	       0x24a434370 __select + 8

If we ignore all those threads, that leaves only one thread, edited down for clarity:

Thread 59 Dispatch queue: com.apple.network.connections:
0   libsystem_c.dylib             	       0x1a7493cc8 strcspn + 32 
1   libsystem_trace.dylib         	       0x1c1269f00 os_log_fmt_compose + 140 
2   libsystem_trace.dylib         	       0x1c1262a74 _os_log_impl_flatten_and_send + 8972 
3   libsystem_trace.dylib         	       0x1c1265f5c _os_log_send_and_compose_impl + 236 
4   Network                       	       0x19a0166e8 nw_mem_buffer_allocate + 232 
5   libboringssl.dylib            	       0x1c2af0b28 nw_protocol_boringssl_read_one_record + 160  [inlined]
...
19  Network                       	       0x19a0017ac invocation function for block in nw_channel_create(nw_context*, unsigned char*, unsigned int, void*, unsigned int, bool, bool, bool*) + 76 
20  libdispatch.dylib             	       0x1d5bd41e4 _dispatch_client_callout + 16 
...
34  libdispatch.dylib             	       0x1d5bcd6ac _dispatch_workloop_worker_thread + 720 
35  libsystem_pthread.dylib       	       0x1fa7bc3b0 _pthread_wqthread + 292 
36  libsystem_pthread.dylib       	       0x1fa7bb8c0 start_wqthread + 8

What's critical here is that you're in a memory allocation function ("nw_mem_buffer_allocate") that's choosing to log (by calling os_log). That's an immediate red flag— by definition, memory functions are performance sensitive, so they tend to only resort to logging when "something" has gone so wrong that they can't really do anything else. In addition, you’re not inside the allocator itself (like "malloc"), which means this had to be reacting to a valid return value, not something direct like memory corruption. malloc can really only fail in one way; most likely, the answer here is that malloc returned NULL.

That's actually supported by this as well:

Exception Type:    EXC_CRASH (SIGSEGV)
Exception Codes:   0x0000000000000000, 0x0000000000000000

Termination Reason:  Namespace SIGNAL, Code 11, Segmentation fault: 11

The "Code" there is the mach exception code, with "11" being EXC_RESOURCE.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Part 2:

No, not really. Memory exceptions (what a seg fault is) happen because you’re accessing memory that you either never allocated or have already freed, neither of which will happen due to direct lack of memory. Keep in mind that your app can't really "run out" of memory in the way you're describing.

SO, the issue here is that the term "memory" is commonly used to describe two separate, but distinct, concepts:

  1. How much RAM your process is using.

  2. How much address space your process has been given by the system.

The important thing to understand here is that those two factors are somewhat independent of each other. In simple terms, address space is what you actually "use" when you call “malloc," but RAM usage doesn't change until you actually "touch" the memory you've malloc'd. Similarly, the question here:

is it possible that memory usage has increased significantly in iOS 26.4 compared to previous OS versions?

...doesn't really make "sense" in the context of address space. Real RAM usage changes considerably from release to release, but the address space is a fixed limit that doesn't change all that much from release to release. More to the point, it's a high enough limit that most apps never come close to hitting. Unfortunately, I think that's the limit you're hitting. There's a chart at the bottom of the crash log that lays out your VM state, but this is the one that jumped out at me:

mapped file                      712.0M     1518 

My guess is that you're mmap'ing a large data file, and that file's size has now crept up to the point where you're exhausting address space.

Finally, a few other things worth noting:

(1) Where did this crash log come from, and was a 3rd party crash reporter involved? There are a number of threads missing from the log, which generally indicates that "something" edited the log. Some 3rd party crash services do this to "hide" their own crashing infrastructure, since it's considered irrelevant. However, my own perspective is that I'd actively avoid any service that worked that way, since it opens the door to the service hiding problem instead of helping you find them.

(2) A number of your threads are running NSRunLoop on a GCD queue:

6   CoreFoundation                	       0x19b9a9f94 __CFRunLoopRun + 1188 ()
7   CoreFoundation                	       0x19b9a91d0 _CFRunLoopRunSpecificWithOptions + 532 ()
8   Foundation                    	       0x198c1ccf0 -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 212 ()
9   Foundation                    	       0x198c212fc -[NSRunLoop(NSRunLoop) run] + 64 ()
10 UnityFramework                	       0x11d549e4c
11 libdispatch.dylib             	       0x1d5bba9a8 _dispatch_call_block_and_release + 32 ()
...
20 libsystem_pthread.dylib       	       0x1fa7bc374 _pthread_wqthread + 232 ()
21 libsystem_pthread.dylib       	       0x1fa7bb8c0 start_wqthread + 8

This is a bad idea. More specifically, one of two things is going on:

  1. This is a “long-lived thread", in which case you've basically "stolen" one of GCD threads for now’s real benefit.

  2. This is a “short-lived thread", in which case this is just a bad idea.

Expanding on that second point, the "point" of NSRunLoop is to allow a thread to listen for Mach messages from different sources and then route those messages to the appropriate callback whenever they're received. Most apps really only need to do this on one thread (the main thread), but there are cases where using a second thread to keep work off the main thread might be useful. However, beyond that point, extra threads are a waste of resources and create new bug opportunities, since every new runloop is a new opportunity to waste resources (particularly Mach ports).

Finally, loosely related to both of those points, my general analysis here assumes that I'm seeing "all" of the relevant information. I think I'm right about the general cause, but it's also possible that the missing threads or other data would completely change my answer.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Crashes occur on iOS 26.4
 
 
Q