What does RunningBoard do? 4 Assertions
This week’s dive into RunningBoard tackles one of the central questions: this subsystem repeatedly uses the term assertion, but what are these assertions, and how does RunningBoard handle them?
In computing, assertions may have their origin in hardware verification languages like Verilog, where they’re used to state required conditions in declarative form. They appear to have entered macOS through the background service assertiond
, which made a name for itself as a killer of processes and apps. Power assertions have been noted in the log and elsewhere for at least the last decade, and are mentioned in IOPMLib, part of IOKit. Since macOS Catalina, assertions have been at the centre of RunningBoard, which remains essentially undocumented.
Developer app
To get a better idea of how assertions are used, I launched Apple’s Developer app on a Mac mini M4 Pro running macOS 15.5, and followed log entries for a period of over 14 seconds from the start of the launch process. Although RunningBoard’s job description records this app’s platform as 6, typical of a Catalyst app, in other log entries it’s claimed not to be a Catalyst app.
At an arbitrary start time of 01.126 seconds, LaunchServices decided to launch this app initially through CoreServicesUIAgent, which 0.04 seconds later requested RunningBoard to execute the launch request. This eventually led to a connection being initialised to FrontBoard Scene Manager, where the app was registered as a new scene, and activated.
Example assertion
FrontBoard set the process visibility to Foreground:01.593239 com.apple.FrontBoard [app<application.developer.apple.wwdc-Release.9312198.9312203~>:2946] Setting process visibility to: Foreground
RunningBoard then announced it was acquiring a new assertion, giving its descriptor and the PID of the target process01.593248 com.apple.runningboard Acquiring assertion: <RBSAssertionDescriptor| "com.apple.frontboard.after-life.subordinate" ID:(null) target:2946>
01.593288 com.apple.runningboard PERF: Received request from [osservice<com.apple.uikitsystemapp(501)>:748] (euid 501, auid 501) (persona (null)): acquireAssertionWithDescriptor:error:
01.593289 runningboardd acquireAssertionWithDescriptor
A fuller description followed, including the RunningBoard ID, and the attributes of the assertion01.593324 com.apple.runningboard Acquiring assertion targeting [app<application.developer.apple.wwdc-Release.9312198.9312203(501)>:2946] from originator [osservice<com.apple.uikitsystemapp(501)>:748] with description <RBSAssertionDescriptor| "com.apple.frontboard.after-life.subordinate" ID:424-748-2228 target:2946 attributes:[
<RBSDomainAttribute| domain:"com.apple.frontboard" name:"AfterLife-Subordinate" sourceEnvironment:"(null)">
]>
This assertion was made active, and RunningBoard stated how many assertions were currently targeting that process01.593343 com.apple.runningboard Assertion 424-748-2228 (target:[app<application.developer.apple.wwdc-Release.9312198.9312203(501)>:2946]) will be created as active
01.593389 com.apple.runningboard app<application.developer.apple.wwdc-Release.9312198.9312203(501)> is now targeted by 11 assertions
That triggered a state update for the process01.593400 runningboardd state update
In this case, RunningBoard couldn’t do anything, so left the process’s assertions as they were01.593461 com.apple.runningboard _checkForSuspendableAssertionCycle for app<application.developer.apple.wwdc-Release.9312198.9312203(501)> bailing out since it's not holding a suspendable assertion
01.593466 com.apple.runningboard Removing 0 assertions
This did, though, alter the inheritance of existing assertions01.593556 com.apple.runningboard Process: [app<application.developer.apple.wwdc-Release.9312198.9312203(501)>:2946] has changes in inheritances: {(
<RBSInheritance| environment:(none) name:com.apple.launchservices.userfacing origID:424-391-2215 0>,
<RBSInheritance| environment:(none) name:com.apple.launchservices.userfacing origID:424-391-2215 0>,
<RBSInheritance| environment:(none) name:com.apple.launchservices.userfacing origID:424-391-2214 0>,
<RBSInheritance| environment:(none) name:com.apple.frontboard.visibility origID:424-420-2216 0>
)}
This completed the acquisition of this assertion, and the process’s new state was calculated01.593564 com.apple.runningboard Finished acquiring assertion 424-748-2228 (target:[app<application.developer.apple.wwdc-Release.9312198.9312203(501)>:2946])
01.593741 com.apple.runningboard Calculated state for app<application.developer.apple.wwdc-Release.9312198.9312203(501)>: running-active (role: UserInteractiveFocal) (endowments: <private>)
This was all accomplished in around 0.0005 seconds. FrontBoard then continued processing the app’s scene01.593743 com.apple.FrontBoard Ingesting properties from UIApplicationSceneSettings...
RunningBoard assertion numbers are of the form 424-748-2228, where the second group 748 is the PID of the source of the assertion, and the third group 2228 is a sequential number.
Assertions recorded
- Assertion 424-620-2211 for LaunchServices to launch the app. For this, RunningBoard created its job description with its process ID of 2946, assigned it memory limits, stated the process will be managed, and stated it was running-active with a role of UserInteractive.
- Assertion 424-424-2212 RunningBoard Underlying Assertion. RunningBoard stated the process will be created as active, calculated its processStartTime, created a new RunningBoard Coalition with an ID of 4460, set its Jetsam priority to 0 (the lowest priority over memory use), and set its Darwin GPU to “deny”. Its state was given as running-interactive-NotVisible with a taskState of 4.
- Assertion 424-391-2213 foregroundApp 2946. This changed its role to UserInteractiveNonFocal, and was repeated in assertion 424-391-2214.
- Assertion 424-391-2215 frontmost 2946. RunningBoard changed it to running-active-NotVisible, with a Jetsam priority of 100 (extremely unlikely to be killed to free memory), and Darwin GPU to “allow”.
- Assertion 424-391-2217 LaunchServices notification. It was changed to running-active with a role of UserInteractiveFocal, handshaking took place with the process, and the launch request was recorded. Slightly later, RunningBoard announced it had started “death monitoring” of the process, in case its launch request was denied and the process was killed.
- Assertion 424-748-2218 FrontBoard Bootstrap Background. Following this, the process acquired its first power assertion ID 34241, outside of RunningBoard.
- Assertion 424-2946-2219 Shared Background Assertion
- Assertion 424-655-2220 File Coordination Claim, the first of a series of five similar assertions. For each, RunningBoard recorded Prevent Task Suspend, Prevent Task Throttle Down. After the last it checked for a Suspendable Assertion Cycle, then removed several assertions held for the process.
- Assertion 424-2946-2227 App Nap adapter assertion. RunningBoard then enabled and configured AppNap for the process, and set the AppNap state.
- Assertion 424-748-2228 FrontBoard AfterLife-Subordinate. This is the assertion detailed above.
- Assertion 424-748-2229 FrontBoard Visibility Workspace Foreground Focal. With this, RunningBoard set the process to running-active-Visible with taskState 4.
- Assertion 424-420-2230 App Drawing. Following that,
storekitagent
was running as PID 2947, accompanying the Developer app. - Assertion 424-2946-2232 CFNetwork StorageDB.
- Assertion 424-2946-2233 System Animation Fence.
- Assertion 424-420-2234 App Visible. Following that,
uikitsystemapp
was drawing, presumably for the Developer app. - Assertion 424-420-2236 FuseBoard Process Window State Visible.
- Assertion 424-2946-2238 system animation fence, which was repeated a total of five times.
- Assertion 424-2946-2244 Shared Background Assertion 1, following which were two more assertions for system animation fence.
- Assertion 424-2946-2247 com.apple.CFNetwork.StorageDB again.
- Assertion 424-655-2248 File coordination claim, repeated in Assertion 424-655-2250.
All these assertions were completed in 14 seconds.
Reading RunningBoard
As shown in the series of assertions recorded in the log for the Developer app, RunningBoard provides a detailed account of milestones through the launch and early running of this app, covering much other than its security and TCC activity.
This starts with a job description containing a great deal of useful information about the app, when it’s neither visible nor focal. At that stage it’s given a minimal Jetsam priority, putting it in the front line to be forcibly quit if memory was short, and it’s denied access to the GPU. As launch proceeds, its Jetsam priority is raised to 100 and it’s allowed GPU access. Its role is then changed to UserInteractiveFocal, its window management is handled by FrontBoard and it becomes visible, and able to undergo AppNap. Two supporting services are engaged, storekitagent
to handle its data, and uikitsystemapp
to draw its interface.
Once the novelty of RunningBoard had worn off, I had come to consider its incessant chatter in the log as a distraction. However, a log extract obtained with the subsystem set to com.apple.runningboard
provides a detailed account of events during an app’s life cycle, without the nuisance of privacy censorship, or the app having to make its own log entries.
Key points for close reading of the log
- Set a predicate for obtaining log entries for the
com.apple.runningboard
subsystem, and initially filter entries onAcquiring assertion
in the Messages field. - Identify the Process ID of interest.
- Track assertion descriptions, giving the reason for each assertion.
- Note assertion IDs, and interpret them with the aid of the PID given in their second number field.
- Follow assertions for linked processes through their PIDs.