Post not yet marked as solved
I implemented a multithreaded app, but there was a thread-related crash in the app, I don't understand why this happened, the corresponding stack trace is as follows.
Thread 15 Crashed:: Dispatch queue: com.apple.root.default-qos
0 libsystem_kernel.dylib 0x1a849ad98 __pthread_kill + 8
1 libsystem_pthread.dylib 0x1a84cfee0 pthread_kill + 288
2 libsystem_c.dylib 0x1a840a340 abort + 168
3 libc++abi.dylib 0x1a848ab08 abort_message + 132
4 libc++abi.dylib 0x1a847a950 demangling_terminate_handler() + 336
5 libobjc.A.dylib 0x1a8370320 _objc_terminate() + 144
6 libc++abi.dylib 0x1a8489ea4 std::__terminate(void (*)()) + 20
7 libc++abi.dylib 0x1a8489e40 std::terminate() + 64
8 libdispatch.dylib 0x1a830c1c8 _dispatch_client_callout + 40
9 libdispatch.dylib 0x1a831da04 _dispatch_root_queue_drain + 680
10 libdispatch.dylib 0x1a831e104 _dispatch_worker_thread2 + 164
11 libsystem_pthread.dylib 0x1a84cc324 _pthread_wqthread + 228
12 libsystem_pthread.dylib 0x1a84cb080 start_wqthread + 8
Post not yet marked as solved
I implemented an NSXPC for inter-process data transfer, and the data transferred is NSDictionary.
However, a crash occurred during transmission.
The corresponding crash logs are as follows
Thread 16 Crashed:: Dispatch queue: xpc.test.queue
0 libobjc.A.dylib 0x1945a24d0 objc_retain + 16
1 Foundation 0x1956b7764 -[NSDictionary(NSDictionary) encodeWithCoder:] + 604
2 Foundation 0x195686d9c -[NSXPCEncoder _encodeObject:] + 520
3 Foundation 0x19568c154 _NSXPCSerializationAddInvocationWithOnlyObjectArgumentsArray + 120
4 Foundation 0x19568c000 -[NSXPCEncoder _encodeInvocationObjectArgumentsOnly:count:typeString:selector:isReply:into:] + 212
5 Foundation 0x195684f98 -[NSXPCConnection _sendInvocation:orArguments:count:methodSignature:selector:withProxy:] + 1448
6 Foundation 0x19568d584 -[NSXPCConnection _sendSelector:withProxy:arg1:] + 132
7 Foundation 0x19568d4a8 _NSXPCDistantObjectSimpleMessageSend1 + 68
8 TestDemo 0x1041e9308 0x104184000 + 414472
9 libdispatch.dylib 0x1945565f0 _dispatch_call_block_and_release + 32
10 libdispatch.dylib 0x1945581b4 _dispatch_client_callout + 20
11 libdispatch.dylib 0x19455f8a8 _dispatch_lane_serial_drain + 668
12 libdispatch.dylib 0x194560404 _dispatch_lane_invoke + 392
13 libdispatch.dylib 0x19456ac98 _dispatch_workloop_worker_thread + 648
14 libsystem_pthread.dylib 0x194718360 _pthread_wqthread + 288
15 libsystem_pthread.dylib 0x194717080 start_wqthread + 8
want to know if there is any way to check if NSDictionary data is transferable, NSDictionary data is generated dynamically, and the assignment method used is Info[@ "baseInfo"] = ***. Is this method necessary to determine whether *** is not nil?
Post not yet marked as solved
I have another NSXPC problem, and the problem goes like this
NSXPC server implements an interface -(void) callbackWithInfo:(NSDictionary*)log reply:(void (^)(bool))action;
The NSXPC client implements a method that will call the interface in a loop and perform a timeout operation. If the server returns to the interface and does not call the action after 1s, the client will perform subsequent operations. The callbackWithInfo interface is then called again, and the cycle continues.
client code:
The general structure is as follows
while(true){
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[serverProxy callbackWithInfo:InfoDic reply:^(bool action) {
if(flag != NO){
flag = action;
}
}];
dispatch_semaphore_signal(semaphore);
});
if(dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, self.waitTime *NSEC_PER_MSEC)) != 0){
NSLog(@"flag: %d", flag);
}
sleep(0.1);
}
If the action callback is not invoked on the server, the number of FDS on the client increases. As a result, the process cannot open the file, or too much program context information is generated. As a result, the NSXPC interface fails to be invoked.
Now I can not operate on the server side, how can the client side implement the code to ensure that the action will not be punished, and the fd will not increase.
Post not yet marked as solved
I am currently writing an agent for endpoint security. I cannot connect the application and the xpc service. I start the plist with launchctl and then open the application, but it does not connect and the application runs dysfunctionally. I leave the code of the ViewController in the application and the XPCConnection in the xpc service below.
Note: I create the XPC service in Xcode like a normal application and write it as a service application with "Application is background only"
ViewController.swift
func establishConnection() {
XPCConnection.shared.connectToDaemon(bundle: Bundle.main, delegate: self) { success in
DispatchQueue.main.async { [self] in
if !success {
controlButton.isEnabled = false
configMenuStatus(start: false, stop: false)
alertWithError(error: "Unable to start monitoring for broken connection with daemon.")
} else {
Logger(.Info, "Connect to daemon successfully.")
}
}
}
}
XPCConnection.swift
func connectToDaemon(bundle: Bundle, delegate: ClientXPCProtocol, handler: @escaping (Bool) -> Void) {
guard connection == nil else {
Logger(.Info, "Client already connected.")
handler(true)
return
}
guard getMachServiceName(from: bundle) == ClientBundle else {
handler(false)
return
}
let newConnection = NSXPCConnection(machServiceName: DaemonBundle)
newConnection.exportedObject = delegate
newConnection.exportedInterface = NSXPCInterface(with: ClientXPCProtocol.self)
newConnection.remoteObjectInterface = NSXPCInterface(with: DaemonXPCProtocol.self)
newConnection.invalidationHandler = {
self.connection = nil
Logger(.Info, "Daemon disconnected.")
handler(false)
}
newConnection.interruptionHandler = {
self.connection = nil
Logger(.Error, "Daemon interrupted.")
handler(false)
}
connection = newConnection
newConnection.resume()
let proxy = newConnection.remoteObjectProxyWithErrorHandler { error in
Logger(.Error, "Failed to connect with error [\(error)]")
self.connection?.invalidate()
self.connection = nil
handler(false)
} as? DaemonXPCProtocol
proxy!.connectResponse(handler)
handler(true)
}
This is the error photo, the application continues to work
First, I checked to see if I had made a mistake in the bundle identifier, but I could not find an error, and then I realized that I had not run the launchd service. Then I ran it, but it did not make any sense. What I am trying to do is to connect and run the network extension and endpoint security with this service, but the xpc service does not connect to each other.
Post not yet marked as solved
Development Environment:
Xcode Version: 14.3.1
macOS Ventura Version: 13.6.2
Architecture: Intel
I am developing a macOS app with an accompanying XPC service and am encountering an issue where the XPC connection is immediately invalidated upon trying to establish it. The error message received is:
Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.appname.macos.app-name-xpc was invalidated." UserInfo={NSDebugDescription=The connection to service named com.appname.macos.app-name-xpc was invalidated: failed at lookup with error 3 - No such process.}
Here's what I have verified so far:
The XPC service has the correct CFBundleIdentifier and is located within the Contents/XPCServices directory of my app's bundle.
Info.plist for the XPC service has ServiceType set to Bundled.
The XPC service target's Installation Directory is the default location for XPC services (@executable_path/../XPCServices).
Code signing and entitlements have been verified for both the main app and the XPC service, and disabling the sandbox doesn't resolve the issue.
The main app and XPC service are part of the same App Group, and both have the App Sandbox capability enabled.
Here's a snippet of the Swift code that establishes the XPC connection:
let xpcConnection = NSXPCConnection(serviceName: "com.appname.macos.app-name-xpc")
xpcConnection.remoteObjectInterface = NSXPCInterface(with: ServiceProtocol.self)
xpcConnection.resume()
And here's the ServiceProtocol for reference:
@objc public protocol ServiceProtocol: NSObjectProtocol {
@objc func executeUnixExecutable(arguments: [String], completionHandler: @escaping (ResultType) -> Void)
func interruptUnixExecutable()
func closeUnixExecutablePipes()
}
When I run the app, the connection is invalidated without any further details as to why. I'm not sure if I'm missing a configuration step or if there's an issue with my XPC service setup.
Has anyone experienced this issue or have suggestions on what else I can check to resolve this?
Post not yet marked as solved
Hi,
Is there a way to restrict calls to a launch daemon?
Can I allow only my app to use my daemon?
cheers,
sivan
Post not yet marked as solved
I would like to develop a macOS application in Swift. This application will consist of 2 programs: a main program to be run by the user (standard account) and another one that will run with root privileges. The second program will only be invoked to perform privileged tasks. Running the main program under root permanently would be too risky.
XPC will be used to trigger calls from the main program to the privileged program.
How can I secure the privileged program to ensure that the calling program is indeed my main program and not another unauthorized program?
Post not yet marked as solved
I’m trying to implement XPC Rendezvous like Quinn described in many awesome posts on here but I’m now at a stuck point were I just have no idea.
I want to communicate with a Safari extension via XPC and also a helper application which led me to XPC Rendezvous (https://developer.apple.com/forums/thread/715338) because a XPC Service in the Extension is scoped to the container. I then made a Command Line Target and added it like its described here (https://developer.apple.com/documentation/xcode/embedding-a-helper-tool-in-a-sandboxed-app
) and also took the xpc test code and inspiration to set up my launch agent from here (https://developer.apple.com/documentation/servicemanagement/updating_your_app_package_installer_to_use_the_new_service_management_api). This command line tool should do the management for the XPC connections because it’s not in the sandboxed container.
The tool sets up the xpc connection like in the sample code directly and not in a XPC Service added via a Target template. It exposes the Mach Service.
And that looks like its building fine after some fighting but the service just wont start - I saw it trying in console and after running it in Xcode and finally finding the crash report - it brought me there (https://developer.apple.com/forums/thread/706390)
I have Process is not in an inherited sandbox. - and thinking about it, it makes sense because I first thought its just because it ran through Xcode, but its crashing this way also as a LaunchAgent.
I mean it does make sense - there is nothing to inherit because it’s spawned by launchd - and that’s what I want isn’t it - to make the Rendezvous?
Okay I thought now removing com.apple.security.inherit brings it in its own Sandbox (its needs sandboxing) but this also crashes the process because of the sandbox. Also after adding it to the App Group. What am I missing here or what do I want to accomplish? Do I want to inherit the sandbox? I guess not the helper should have its own.
The only difference I see in comparison to SMAppServiceSampleCode is it moves the product in Copy Bundle Resources, and I have a Copy Files Phase with Destination: Executables (Like the other sample code said - and that’s looks “more correct” - and well SMAppServiceSampleCode isn’t sandboxed.
I then tried making a new Command Line Target and just added App Sandbox Capability and tried to run this fresh one - and that also crashes. This makes me think I’m just ****** somewhere but I have read now everything I could find.
I’m happy to provide any Code or crash logs but I dont know what part is really relevant here, It looks like the LaunchAgent gets installed correctly and wants to run but the sandbox is preventing me. The Bundle Identifier and XPC device name of the helper starts with my teamID
(I got that from here https://developer.apple.com/forums/thread/703702)
What could I be doing wrong?
Thanks a lot!
Benjamin
Post not yet marked as solved
Hi Team,
I have a Network Extension application and UI frontend for it.
The UI frontend talks to the Network Extension using XPC, as provided by NEMachServiceName.
On M2 machine,
The application and XPC connection works fine on clean installation.
But, when the application is upgraded, the XPC connection keeps failing.
Upgrade steps:
PreInstall script kills the running processes, both UI and Network Extension
Let installation continue
PostInstall script to launch the application after installation complete.
Following code is successful to the point of resume from UI application
NSXPCInterface *exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(IPCUIObject)];
newConnection.exportedInterface = exportedInterface;
newConnection.exportedObject = delegate;
NSXPCInterface *remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(IPCExtObject)];
newConnection.remoteObjectInterface = remoteObjectInterface;
self.currentConnection = newConnection;
[newConnection resume];
But it fails to get the object
id<IPCExtObject> providerProxy = [self.currentConnection remoteObjectProxyWithErrorHandler:^(NSError *registerError) {
}];
Please note, this only fails for M2. For M1, this exact code is running fine.
Additionally, if I uninstall the application by dropping it in Trash and then installing the newer version, then too, the application works fine.
Post not yet marked as solved
I am looking for a solution to transfer data between two completely separate processes (not from the same group). I did a lot of research, but the solutions were mostly for processes that are in a group. Is there a method? (It doesn't matter if the app is sandboxed, I can disable it).
My goal is to communicate between a bundle(plugin) that is activated on the Mac login page and an XPC service and transfer data from the service to the bundle.
Hi everyone :)
I'm exploring XPC these days; more specifically, I'm trying to establish a connection between a macOS application and an XPC service.
I succeeded in establishing the connection, but now I'm trying to verify the incoming connection by using SecCodeCopyGuestWithAttributes, passing it an audit token.
But I got the following error:
2024-01-18 10:43:06.805435+0100 DemoService[1627:7118397] [logging-persist] cannot open file at line 46922 of [554764a6e7]
2024-01-18 10:43:06.805452+0100 DemoService[1627:7118397] [logging-persist] os_unix.c:46922: (0) open(/private/var/db/DetachedSignatures) - Undefined error: 0
Cannot get SecCode: 100001 - UNIX[Operation not permitted]
Audit token: Optional(32 bytes)
The last two lines come from my code:
class XPCClientValidator {
var secCodeOptional: SecCode? = nil;
func identifyGuest(for connection: NSXPCConnection) -> Bool {
let auditToken = AuditToken.extractToken(from: connection)
let hostSecCode: SecCode? = nil; // This is a way to indicate that the code signing root of trust hould be used as host.
let attributes = [ kSecGuestAttributeAudit: auditToken ] as CFDictionary
let secFlags = SecCSFlags(rawValue: 0)
// Asks a code host to identify the guest given the audit token
let status: OSStatus = SecCodeCopyGuestWithAttributes(hostSecCode, attributes, secFlags, &self.secCodeOptional)
if (status != errSecSuccess) {
let msg = SecCopyErrorMessageString(status, nil)!
print("Cannot get SecCode: \(status) - \(msg)")
print("Audit token: \(String(describing: auditToken))")
return false
}
guard let _ = secCodeOptional else {
NSLog("Couldn't unwrap the secCode")
return false
}
return true
}
}
I saw a few posts on the forum, but nothing helped me to solve this issue.
The complete source code is here: https://github.com/tony-go/XPCDemo/tree/secure-xpc
Note: If you want to reproduce it, you have to:
start the app
type a random input
click on "uppercase it"
Post not yet marked as solved
Hi there :)
I try to put an Xcode project in place within a LaunchAgent.
The ultimate goal is to have an "application" with two component:
macOS application with just an basic UI
all the logic happens in a LaunchAgent that runs on background and is launch at startup.
The macOS app uses XPC to send messages to the agent that will run either the app is opened or not.
I struggled at first having this error (for the agent):
An XPC Service cannot be run directly.
Then I found using MachServices key in the .plist of the agent fixes the issue, plus:
let listener = NSXPCListener.init(machServiceName: "com.tonygo.NetworkMonitorAgent")
Then I wonder:
Do we have somewhere a documentation about how to setup a LaunchAgent in Xcode
I create the plist of the agent on side and run it manually, I could do this in a more automatic way
How could I package a macOS applciation that will contains the agent, install it and load the agent?
Note: This is mainly for learning and understanding what we could do at each level (XPCService, LaunchAgents, LaunchDaemon, etc.).
Post not yet marked as solved
I asked a similar question last year, and got no responses. I've written a much simpler (no network extension!) case that seems to demonstrate what I'm confused about.
Simple app with an XPC service. I have an ObjectiveC class TestObject which has an NSString* and an NSData* (which I never actually use). I have a protocol defined in Swift:
@objc protocol XPCTestServiceProtocol {
func logData(entry: TestObject) -> Void
func logData(entry: TestObject, completion: ((String) -> Void))
}
In the Switt XPC service, the code is:
class XPCTestService: NSObject, XPCTestServiceProtocol {
var totalBytes = 0
var lastName = ""
@objc func logData(entry: TestObject) {
totalBytes += (entry.data?.count ?? 0)
}
@objc func logData(entry: TestObject, completion: ((String) -> Void)) {
totalBytes += (entry.data?.count ?? 0)
completion("Finished")
}
I've got this code in the ObjC app:
id<XPCTestServiceProtocol> proxy = [self.connection remoteObjectProxyWithErrorHandler:^(NSError* error) {
self.stopRun = YES;
NSLog(@"Proxy got error %@", error);
}];
while (self.stopRun == NO) {
@synchronized (self) {
NSNumber *objNum = [NSNumber numberWithUnsignedLongLong:self.count++];
NSString *objName = [NSString stringWithFormat:@"Object %@", objNum];
TestObject __weak *toWeak = to;
#if USE_COMPLETION
[proxy logDataWithEntry:to completion:^(NSString *str) {
to = nil;
}];
#else
[proxy logDataWithEntry:to];
#endif
}
}
attached to a start button (and self.stopRun is set by a stop button, this is all super simple).
So I run that, start the test, and things start going (122k calls/second it says). According to Activity Monitor, my app is using about 1gbyte after 20 seconds or so.
However, if I run it under Instruments' Leaks template... Activity Monitor says it's used only about 60mbytes. (And at the end of the run, Instruments says it's used about 30mbytes.)
Now... if I use the completion and a synchronous proxy, then even without Instruments, Activity Monitor says it's 60mbytes or so.
Is the memory reported by Activity Monitor real? Or not real?
Post not yet marked as solved
Hello,
we are currently working on a plan to migrate our app suite from Developer ID binaries inside a simple pkg installer to macOS app store distribution.
The reason we are using an installer is that there are multiple binaries inside that communicate via XPC and we need to install the respective launchd plist in /Library/LaunchDaemons and /Library/LaunchAgents:
1 root daemon
1 agent that has minimal UI and lives in the system menu bar
1 embedded command line utility in user agent
1 embedded FileProvider extension in user agent
1 embedded Action Extension in user agent
1 agent that only does OAuth stuff
Looking through Updating helper executables from earlier versions of macOS I can install the root daemon with SMAppService.daemon(plistName:) and the OAuth helper with SMAppService.agent(plistName:). For the main application I only found SMAppService.mainApp which does not accept a property list configuration. Therefore, I have no place to put my MachServices array and so the File Provider extension, the Action Extension, and the embedded command line utility have no way to talk to the user agent.
Currently, XPC is used in between these processes:
user agent -> root daemon
command line utility -> user agent
action extension -> user agent
file provider extension -> user agent
user agent -> file provider extension: that already works through NSFileProviderServicing
I know app-to-app communication only works through launchd for security reasons, but these applications are all part of the same app group (except the root daemon obviously).
My question is what is the proper way of starting the user agent so XPC from other binaries just work ™️?
Any input is much appreciated!
Post not yet marked as solved
I want to
build an Xcode Source Code Editor extension
that triggers an XPC service
shows a gui that can handle user interactions
Is it possible in any way ?
what are the alternatives to display the UI and allow the user to interact on it ?
Post not yet marked as solved
I am currently working on planning a multi-component software system that consists of an Audio Server Plugin and an application for user interaction. I have very little experience with IPC/XPC and its performance implications, so I hope I can find a little guidance here.
The Audio Server plugin publishes a number of multi-channel output devices on which it should perform computations and pass the result on to a different Core Audio device. My concerns here are:
Can the plugin directly access other CoreAudio devices for audio output or is this prohibited by the sandboxing? If it cannot, would relaying the audio data via XPC be a good idea in terms of low latency stability?
Can I use metal compute from within the Audio Server plugin? I have not found any information about metal related sandboxing entitlements. I am also concerned about performance implications as above.
Regarding the user interface application, I would like to know:
If a process that has not been started by launchd can communicate with the Audio Server plugin using XPC. If not, would a user agent instead of an app be a better choice? Or are there other communication channels that would work with sandboxing?
Thank you very much!
Andreas
Post not yet marked as solved
Greetings!
I've added a Matter accessory via the Apple Home app. In my app, I'm attempting to commission this device and add it to my fabric. However, when I try to open the commissioning window, I receive an error stating, MTRBaseDevice doesn't support openCommissioningWindowWithDiscriminator over XPC.
It appears that opening a commissioning window via an XPC connection is not yet supported. Is there another method to commission the device? Can I retrieve the setup payload from the MTRBaseDevice object or the shared MTRDeviceController?
Here's the simplified version of my code:
var home: HMHome // HMHome received via HMHomeManager
var accessory: HMAccessory = home.accessory[0] // my Matter-supported accessory
let deviceController = MTRDeviceController.sharedController(
withID: home.matterControllerID as NSCopying,
xpcConnect: home.matterControllerXPCConnectBlock
)
let device = MTRBaseDevice(
nodeID: accessory.matterNodeID as NSNumber,
controller: deviceController
)
device.openCommissioningWindow(
withDiscriminator: 0,
duration: 900,
queue: .main) { payload, error in
if let payload {
// payload not received
} else if let error {
// I'm getting here "Error Domain=MTRErrorDomain Code=6 "(null)""
// and "MTRBaseDevice doesn't support openCommissioningWindowWithDiscriminator over XPC" logged in the console
print(error)
}
I'm working on a macOS application that deals with a few external dependencies that can only be compiled for intel (x86_64) but I want the app to run natively on both arm and x86_64.
One idea I have been playing with is to move the x86_64 dependencies to an xpc service compiled only as x86_64 and use the service only the intel machine. However, I can't figure out how to setup my project to compile everything at once...
Any ideas? Is this even possible? If not, I'm open to suggestions...
Thanks
Post not yet marked as solved
We are working on a command line daemon (started with launchd) for a UI to communicate with using XPC. The functions we have been using so far work correctly, but they only take arguments and return void.
We wanted to add a function with a simple reply block to see if the daemon is running or not, and we may need to get data back in the future. But it is not working.
For example, this is working:
if let proxy = connectionToService.remoteObjectProxyWithErrorHandler({ error in
print(error.localizedDescription)
}) as? TheDaemonProtocol {
proxy.doStuff("Test string")
}
But this returns an error "Couldn’t communicate with a helper application."
if let proxy = connectionToService.remoteObjectProxyWithErrorHandler({ error in
print(error.localizedDescription)
}) as? TheDaemonProtocol {
proxy.isUp { reply in
print("reply: \(reply)")
}
}
isUp() is coded to only return true for now.
@objc func isUp(reply: @escaping (Bool) -> Void) {
reply(true)
}
TIA for any help!
Post not yet marked as solved
I've been experimenting with the new low-level Swift API for XPC (XPCSession and XPCListener). The ability to send and receive Codable messages is an appealing alternative to making an @objc protocol in order to use NSXPCConnection from Swift — I can easily create an enum type whose cases map onto the protocol's methods.
But our current XPC code validates the incoming connection using techniques similar to those described in Quinn's "Apple Recommended" response to the "Validating Signature Of XPC Process" thread. I haven't been able to determine how to do this with XPCListener; neither the documentation nor the Swift interface have yielded any insight.
The Creating XPC Services article suggests using Xcode's XPC Service template, which contains this code:
let listener = try XPCListener(service: serviceName) { request in
request.accept { message in
performCalculation(with: message)
}
}
The apparent intent is to inspect the incoming request and decide whether to accept it or reject it, but there aren't any properties on IncomingSessionRequest that would allow the service to make that decision. Ideally, there would be a way to evaluate a code signing requirement, or at least obtain the audit token of the requesting process.
(I did notice that a function xpc_listener_set_peer_code_signing_requirement was added in macOS 14.4, but it takes an xpc_listener_t argument and I can't tell whether XPCListener is bridged to that type.)
Am I missing something obvious, or is there a gap in the functionality of XPCListener and IncomingSessionRequest?