Why would my Mac app be preemptively terminated?

I have a persistent "crash" with at least one of my apps, which appears to be a case of the app either quitting or being force-quit without generating a crash log. The app doesn't subscribe to any sudden termination compatibility or similar. I have a good friend who is a developer who is able to reproduce the issue within minutes, so I've captured a trove of information from him including a complete sysdiagnose. Unfortunately nothing is jumping out at me, and the only things that show up that seem like they might be related are keys like ApplicationWouldBeTerminatedByTAL and NSCanQuitQuietlyAndSafelyKey.

I am kind of grasping at straws and would welcome any inspiration anybody can share. What is TAL and is it something the system could be imposing on my app? If there are circumstances where macOS will preemptively terminate a running app, what are they, and how can I figure out which one is causing the quits in these situatoins? I'd love to be able to reproduce the behavior on my own Mac. If it's something I can prevent, great, if it's not, it would be good to know how to distinguish it from a regular crash for reporting purposes.

Thanks for any help!

Post not yet marked as solved Up vote post of jalkut Down vote post of jalkut
1.1k views

Replies

What is TAL

TAL stands for “transparent application lifecycle”. It was a feature we added to the Mac… gosh… about 10 years ago, to divorce the app’s lifecycle from the lifecycle of its process. One part of this is that macOS can terminate apps that aren’t visible and then relaunch them when they become visible again.

For general background on this, follow the links in the Resume section of this doc in the archive.

I have a persistent "crash" with at least one of my apps, which appears to be a case of the app either quitting or being force-quit without generating a crash log.

So what’s happening at the time the app ‘crashes’? Is it visible on screen? Or lurking in the background?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Oh, thanks Quinn! I missed this reply until now in the hubbub of WWDC week.

Yes, when the app crashes it is apparently always "lurking in the background," so it matches up with the profile of what TAL is purported to do. However, the app hasn't opted in to sudden termination, and reports of the problem suggest the app's icon does disappear from the Dock when the issue occurs. It's also affecting a couple other apps on one of the users' systems, but always the same few apps!

Any other inspirations about things I can ask the person who reproduces it regularly to try? Or things to look for in the log about reasons it might be terminated?

Thanks so much! Daniel

I see now that there is a distinction between "automatic" and "sudden" termination, and I think the "automatic" termination is the one that correlates with TAL. I'll take a closer look at these keys, maybe even if I don't specify support for either one I can enable them to get a better feeling for whether the behavior I then see matches what other users are seeing.

I think I might have a breakthrough. Scanning the sysdiagnose from my friend's Mac I came across this line in launchd.log, which I think correlates with one of the unexpected terminations:

2022-05-03 09:15:22.088718 (gui/501/application.com.red-sweater.marsedit4.384452971.384452977 [13840]) : exited with exit reason (namespace: 15 code: 0xbaddd15c) - OS_REASON_RUNNINGBOARD | <RBSTerminateContext| code:0xBADDD15C explanation:CacheDeleteAppContainerCaches requesting termination assertion for com.red-sweater.marsedit4 reportType:None maxTerminationResistance:NonInteractive attrs:[

When I search my own Mac's launchd logs for RBSTerminateContext, I only find it a few times relating to the Apple News app and some message about Catalyst apps not being permitted to "task-suspend."

Sorry for the blast of follow-up messages, but now with the clue of "RunningBoard" I came across this article, https://eclecticlight.co/2019/11/07/runningboard-a-new-subsystem-in-catalina-to-detect-errors/, which includes an eyebrow-raising sentence:

Catalina brings several new internal features, a few of which have been documented, but others seem to have slipped past silently. Among the latter is an active subsystem to replace an old service assertiond, which can cause apps to unexpectedly terminate – to you and me, crash – in both macOS 10.15 and iOS 13: RunningBoard.

Given the seemingly pertinent RunningBoard termination in the log, and the allusion to "unexpected termination" by the article cited, I think I am on to something here!

I managed to trace this down to the system frameworks level inside the private DeleteCache.framework. It seems that this framework runs a daemon, "deleted" which is responsible for handling requests to free up purgeable space. This is likely to happen when the system notices there isn't much disk space left, or when a 3rd party utility such as CleanMyMac specifically requests (I think via SPI) that the space be purged.

I guess the system considers this enough of an emergency tactic that it doesn't hesitate to proactively terminate the corresponding apps to which the purged caches belong.

Thanks for inspiring me to look into this more deeply, Quinn. I think I'm all set now and hopefully this thread will serve as a reference for others who might run across the mysterious quitting behavior.

Oh, hey Daniel, didn’t notice your user name at first.

Scanning the sysdiagnose from my friend's Mac I came across this line in launchd.log, which I think correlates with one of the unexpected terminations

That is interesting. As you’ve surmised, the exception code 0xbaddd15c (‘bad disc’, which sounds worse than it is) seems to be related to our CacheDelete subsystem. That subsystem is almost entirely internal to the OS, so there’s not a lot of public documentation. The one thing I did find is that deleted has a man page that covers the basics. You can also see aspects of it in properties like NSURLVolumeAvailableCapacityForImportantUsageKey and NSURLVolumeAvailableCapacityForOpportunisticUsageKey, which shows how there’s a difference between how much disk space is actually free at the volume level versus how much disk space can be made free.

CacheDelete won’t delete files out from underneath a running app so, if it needs to delete something, it terminates the app. It should only do that when the app is essentially invisible to the user.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I appreciate the extra information. I also was able to discover that it's a public API, CSDiskSpaceStartRecovery, that kicks off the deleted purging behavior. I'll figure out how to detetct this kind of termination and avoid sending a crash report about it!

If anybody is curious, I wrote a blog post detailing the process of diagnosing this issue: https://bitsplitting.org/2022/06/18/purgeable-mac-apps/

I also was able to discover that it's a public API, CSDiskSpaceStartRecovery

Ah, yes, I knew we had more public API. That one, <CarbonCore/DiskSpaceRecovery.h>, and it’s fellow traveller <CarbonCore/BackupCore.h>, are so obscure.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"