RunningBoard oversees and manages resources for a great many processes, including the bluetoothd service, QuickLook Preview extensions run as XPC services, and the Finder. In a busy period of 1.75 seconds when there were a total of 10,000 log entries, 961 (9.6%) of those came from the com.apple.runningboard subsystem. This article looks at one series, in which RunningBoard manages an XPC service FindMyWidgetPeople, submitted in a Timeline through ChronoCore. If those terms seem unfamiliar, it’s because they’re recent, and may appear in macOS dating back only to Big Sur.
chronod
macOS has several systems to schedule and perform periodic tasks, including launchd for running a task at exact times, and DAS-CTS for background tasks to be scheduled flexibly when conditions are favourable. The most recent among them is the LaunchAgent chronod, which first reached public attention in late 2023 when Norton 360 suddenly started flagging its network connections as being potentially malicious, and some users began reporting it as consuming high CPU % at times.
chronod is the service in the ChronoCore private framework that is completely undocumented, but appears primarily intended to update information for widgets and their related tasks. For this purpose, widgets operate a Timeline to determine when they should have their data updated, as explained by Apple, with additional documentation for the Timeline Provider here.
The example shown here, FindMyWidgetPeople, is particularly interesting, as it’s part of macOS and supplements the Find My service by displaying information about people being followed in that service. Its appearance here is pure serendipity, as the log extract obtained was intended to capture information about RunningBoard’s management of Catalyst apps, and by chance gathered nearly 0.5 seconds of this different log entry series. It came as a complete surprise, as this Mac has never been used to display any Find My widget, so this data gathering wasn’t in response to any user action or even interest.
Task states and Jetsam
RunningBoard often refers to the taskState, a small positive integer. This may be the same as XPC activity states, documented in Apple’s source code as:
ul>
Jetsam is the modern equivalent of the older memorystatus and enableAutomaticTermination option introduced in Mac OS X 10.7 Lion, for automatic termination of a process when macOS needed to free up more memory and that process was idle. With Jetsam, which was initially introduced into iOS, processes don’t have to opt into the system. If a process’s Jetsam priority is 0, it’s first in line to be quit if macOS comes under memory pressure, and the higher the priority the less likely that becomes.
Job description
As is usual with RunningBoard, one of its first tasks before it will monitor any process is to construct its job description, in this case explicitly referred to as an extension overlay, with contents differing from a normal job description. Notable here are:
- Platform is given as 6, the same as that shown for a Catalyst app.
- A special dictionary is given as an XPC Service, including its RunLoopType, whether to join the existing session, and use of the Apple Extension Service.
- Keys for the launched identity are obfuscated by the use of single letters, such as ‘e’ for EUID.
The full job description is given in the Appendix.
Launch
This is initiated when chronod adds FindMyWidgetPeople as a pending task, and sets up its task queue with the task Timeline. Then com.apple.extensionkit reports the process is being launched, and RunningBoard writes the entry
PERF: Received request from [xpcservice<com.apple.extensionkitservice([osservice<com.apple.chronod(501)>:714])(501)>{vt hash: 0}:768:768] (euid 501, auid 501) (persona (null)): lookupHandleForPredicate:error:
and reports it’s executing that launch request. That results in the extension overlay being written to the log, and the entries
com.apple.libxpc.OSLaunchdJob <OSLaunchdJob | handle=CCB2B5A2-A066-4629-A27B-7CB36BD04E8A>: submitExtension created a job
com.apple.runningboard Setting one-shot instance on launch: D4BB1C92-C109-4188-99AB-944F3E0FF0C1
RunningBoard then takes an assertion for the process with an ID of 813, sets its jetsam priority to 40 [0] flag[1], making it unlikely to be quit under memory pressure, and its Darwin priority to the default. The state is updated to running-active-NotVisible, taskState 4. Following entries come from ExtensionKit and chrono
00.154057 com.apple.extensionkit Created new process ExtensionProcess: bundleID: com.apple.findmy.FindMyWidgetPeople instance ID: Optional([_EXExtensionInstanceIdentifier: D4BB1C92-C109-4188-99AB-944F3E0FF0C1]) pid: 813.
00.155004 com.apple.chrono [findmy.FindMyWidgetPeople-12C04A5E0A56] acquired WidgetExtensionRun
Running
com.apple.chrono runs a session to getTimelines for FindMyWidgetPeople, marked with an announcement of the batch start
Batch begin (ti-cb81ae) - locale: en_GB (fixed en_GB)
and various attempts to find people, involving app intents through a getAppIntentsXPCListenerEndpoint. For example,
com.apple.appintents [com.apple.findmy.FindMyWidgetPeople] Establishing a direct connection to the target process via a listener endpoint
com.apple.findmy.findmylocateagent DataManager load LocalStorage friends with types [.follower] count:0
com.apple.findmy.findmylocateagent DataManager load LocalStorage friends with types [.futureFollower] count:0
com.apple.findmy.findmylocateagent DataManager load LocalStorage friends with types [.futureFollowing] count:0
After those comes a torrent of com.apple.SwiftUI updates, and the end of the session
com.apple.chrono Batch end (ti-cb81ae) - success
com.apple.chrono [findmy.FindMyWidgetPeople-12C04A5E0A56] Session operation: `getTimelines(1)` result.
com.apple.chrono [findmy.FindMyWidgetPeople-12C04A5E0A56] WidgetExtensionRun invalidated
com.apple.chrono [8DF9C661]: activity completed
com.apple.chrono [8DF9C661]: task session completed in 0.107574s. time since creation: 0.107752s
com.apple.chrono No tasks pending
com.apple.chrono [findmy.FindMyWidgetPeople-12C04A5E0A56] Session deinit
Rescheduling
With that session complete, com.apple.chrono schedules the next run
Task [168] [com.apple.findmy::com.apple.findmy.FindMyWidgetPeople:com.apple.findmy.FindMyWidgetPeople:-2849723311258918776] Scheduling reload with configuration: [timelineExhausted-2025-07-09T08:00:00+01:00-budgeted-1]
[3F5BCF63]: scheduled activity enqueued after: 2025-07-09T08:00:00+01:00 before: 2025-07-09T08:15:00+01:00 with data class (<private>)
The previous session (outlined above) completed at 2025-07-09T07:59:00+01:00, so the slot allocated for the next session is any time in the next 15 minutes.
Cleaning up
RunningBoard removes all assertions, sets jetsam priority to 0, suspends the task, assigns it a role of None, shuts down all sockets, and sets its Darwin priority to Background, and Darwin GPU to “deny”.
Summary
- RunningBoard monitors and can manage resources for many types of process, including XPC services.
- ChronoCore’s
chronodservice schedules and dispatches data updates for widgets, even those you don’t use, according to their Timeline. - RunningBoard constructs an extension overlay for this type of XPC service rather than a job description.
chronodinitiates a widget update through ExtensionKit to RunningBoard.- RunningBoard manages the XPC service by setting its Jetsam priority, thus determining the likelihood of the process being quit to free up memory if that comes under pressure.
- When the widget update is complete,
chronodends that session and schedules the next run according to the Timeline. - RunningBoard then cleans up and suspends the task.
Appendix: Extension overlay
The equivalent of a RunningBoard job description for an XPC Service.
<dictionary: 0x896b61b60> { count = 2, transaction: 0, voucher = 0x0, contents =
“XPCService” => <dictionary: 0x896b62940> { count = 14, transaction: 0, voucher = 0x0, contents =
“_ManagedBy” => <string: 0x896bb7f30> { length = 22, contents = “com.apple.runningboard” }
“RunLoopType” => <string: 0x896bb5950> { length = 9, contents = “NSRunLoop” }
“Platform” => <int64: 0x9f2093afcb6817df>: 6
“JoinExistingSession” => <bool: 0x1fd757370>: true
“_SandboxProfile” => <string: 0x896bb5b30> { length = 11, contents = “application” }
“_LaunchWatchdogTimeOut” => <int64: 0x9f2093afcb6817ef>: 0
“_AdditionalSubServices” => <dictionary: 0x896b623a0> { count = 1, transaction: 0, voucher = 0x0, contents =
“apple-extension-service” => <bool: 0x1fd757370>: true
}
“_AdditionalProperties” => <dictionary: 0x896b603c0> { count = 1, transaction: 0, voucher = 0x0, contents =
“RunningBoard” => <dictionary: 0x896b63780> { count = 2, transaction: 0, voucher = 0x0, contents =
“RunningBoardLaunchedIdentity” => <dictionary: 0x896b60660> { count = 7, transaction: 0, voucher = 0x0, contents =
“e” => <int64: 0x9f2093afcb681847>: 501
“TYPE” => <int64: 0x9f2093afcb6817cf>: 4
“v” => <data: 0x896174740>: { length = 199 bytes, contents = 0x7b226164646974696f6e616c456e7669726f6e6d656e7456… }
“h” => <int64: 0x9f2093afcb6801bf>: 714
“i” => <string: 0x896bb7480> { length = 35, contents = “com.apple.findmy.FindMyWidgetPeople” }
“r” => <int64: 0x9f2093afcb6817ff>: 2
“H” => <dictionary: 0x896b62fa0> { count = 5, transaction: 0, voucher = 0x0, contents =
“l” => <string: 0x896bb70c0> { length = 17, contents = “com.apple.chronod” }
“t” => <int64: 0x9f2093afcb6817ff>: 2
“TYPE” => <int64: 0x9f2093afcb6817df>: 6
“a” => <int64: 0x9f2093afcb681847>: 501
“p” => <int64: 0x9f2093afcb6817ef>: 0
}
}
“RunningBoardLaunched” => <bool: 0x1fd757370>: true
}
}
“EnvironmentVariables” => <dictionary: 0x896b62b80> { count = 2, transaction: 0, voucher = 0x0, contents =
“EXTENSION_KIT_EXTENSION_TYPE” => <string: 0x896bb5b90> { length = 1, contents = “1” }
“BSServiceDomains” => <string: 0x896bb5fb0> { length = 46, contents = “{“XPCService”:{“Services”:{“MainService”:{}}}}” }
}
“_OmitSandboxParameters” => <bool: 0x1fd757370>: true
“_MultipleInstances” => <bool: 0x1fd757370>: true
“ServiceType” => <string: 0x896bb5e90> { length = 11, contents = “Application” }
“ProgramArguments” => <array: 0x896bb53b0> { count = 1, capacity = 8, contents =
0: <string: 0x896bb75d0> { length = 107, contents = “/System/Applications/FindMy.app/Contents/PlugIns/FindMyWidgetPeople.appex/Contents/MacOS/FindMyWidgetPeople” }
}
“_ManagedBy_Services” => <array: 0x896bb65b0> { count = 1, capacity = 8, contents =
0: <string: 0x896bb60a0> { length = 35, contents = “com.apple.findmy.FindMyWidgetPeople” }
}
}
“CFBundlePackageType” => <string: 0x896bb5e00> { length = 4, contents = “XPC!” }
}
