Upon further investigation I noticed a Jetsam event around this crash implicating the app's process in being terminated due to using too much memory (2GB!) (see report below). Using up all the memory could only be possible if we have an infinite loop, and I also found several similar crash reports, with EXC_BAD_ACCESS and KERN_INVALID_ADDRESS or KERN_PROTECTION_FAILURE with Segmentation Fault 11 and Code 0xb, that indicate this could be caused by an infinite loop.
So, what could cause an infinite loop, but only for MDM installs? I found another thread on this forum (link here) where someone had incurred an infinite loop due to following this code example from WWDC 2013 (link here) where an MDM manager class sets up an observer on NSUserDefaultsDidChangeNotification. Their infinite loop was due to someone putting a write call to UserDefaults in the target method of that observer. >.<
So I checked and, sure enough, we have a write call to UserDefaults in the target method of the observer on NSUserDefaultsDidChangeNotification in our MDM manager. It was wrapped with an ivar to prevent the recursion, but it was not a perfect solution obviously. Something about how our iOS 14 build is optimized or the timing of when the method gets called on those builds triggers the recursion, which doesn't happen in iOS 15.
In any event... the fix would be to not write to UserDefaults in that method if the change we want to make in UserDefaults already exists. So we're trying that, will reply here if it worked.
{
"uuid" : "1b20964b-84fa-329a-b8d0-7ad5df6f42ce",
"states" : [
"frontmost"
],
"killDelta" : 5005,
"genCount" : 0,
"age" : 73179629,
"purgeable" : 0,
"fds" : 50,
"coalition" : 1975,
"rpages" : 196608,
"priority" : 10,
"reason" : "per-process-limit",
"physicalPages" : {
"internal" : [
135870,
60638
]
},
"pid" : 21668,
"cpuTime" : 1.3859840000000001,
"name" : "REDACTED",
"lifetimeMax" : 196608
},