No, the app is not sandboxed and the service is declared as a MachService in plist.
Post
Replies
Boosts
Views
Activity
Correct. I embedded an XPC Service and now it's bundled with the main app in XPCServices folder. So instead of agent(plistName: String) I init the service with daemon(plistName: String).
In order to run the service as a LaunchDaemon I need either (1) register it using SMAppService API (plist is in the app bundle at Contents/Library/LaunchDaemons/ folder) or (2) put the plist to /Library/LaunchDaemons/ and run launchctl load <plist>.
Approach (1) with SMAppService is more user friendly as it provides more visibility and user control by showing 'Background Item needs approval' notification and listing it in Login Items in Settings. So I was looking into migrating (2) launchctl approach to (1) SMAppService.
For the use case of application upgrade (new .pkg file released) we need to re-launch currently running LaunchDaemon from postinstall script. Doing it by invoking launchctl unload and then launchctl load works seamless for end users (for initial installation users are not even aware that a service has been also installed since they were not presented with any visuals).
Using (1) SMAppService it can be done by calling unregister and then register from postinstall script invoking a helper binary within the same app bundle (during initial installation users are presented with above mentioned notification which is great). Unfortunately calling register alone doesn't re-register the service and the old process from old package continues running. In order to kill currently running process it's required to unregister the service first. But unfortunately
let service = SMAppService.daemon(plistName: "com.xpc.example.service.plist")
try await service.unregister()
// try await Task.sleep(nanoseconds: 500_000_000)
try await service.register()
requires experimentally discovered 500ms delay between unregister and register as mentioned in the original post. (Trying another unregister with completion handler doesn't make any difference). Otherwise register throws
Unable to register LaunchDaemon(com.xpc.example.service.plist): Error Domain=SMAppServiceErrorDomain Code=1 "Operation not permitted" UserInfo={NSLocalizedFailureReason=Operation not permitted}
(+ problem #2 with strict requirements of where the helper binary must reside inside application bundle).