Not able to connect to XPCService in a Launch agent

1.1k views Asked by At

I have created an XPC Service .

the server side code briefly is

NSXPCListener *listener = [[NSXPCListener alloc] initWithMachServiceName:@"test.xpcserver"];
listener.delegate = delegate;
 [listener resume];

this is installed as a Launch Agent using info.plist as

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>TestServer</string>
    <key>MachServices</key>
    <dict>
        <key>test.xpcserver</key>
        <true/>
    </dict>
    <key>ProgramArguments</key>
    <array>
        <string>/Applications/test.app/Contents/XPCServices/xpcserver.xpc/Contents/MacOS/xpcserver</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>

The server is running fine and i can see it running with launchctl list

The client side code is in another app and the code for connect is:

connection = [[NSXPCConnection alloc] initWithMachServiceName:@“test.xpcserver” options:0];       
  connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(xpcserverprotocol)]; 
[connection resume]; 
  service = [connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { }];
   [service ServerFunc:@“howdy” withReply:^(NSString *result) {
        NSLog(@"%@",result);
    }];

but not able to connect to server . any pointers as to what going wrong ?

2

There are 2 answers

0
Alex M On

It's hard to tell from what you've posted. Things to check:

  • ensure your listener delegate is implementing right function signature for shouldAcceptNewConnection(). If it's not right, you will not get any error. It should be

- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)conn { your code here }

3
Alexander On

(Posting this for future readers, I imagine OP solved their problem by now :) )

Some other things to check:

  1. Make sure your launch agent/deamon is using the -[NSXPCListener initWithMachServiceName], and not +[NSXPCListener serviceListener].

    • The latter is only useful for regular XPC service (which would be stored in the App's bundle, not in /Library/.... If you mix it up, you'll get a crash report in Console.app that will say:

      Configuration error: Couldn't retrieve XPCService dictionary from service bundle.

  2. In your agent/daemon, don't forget to start the main run loop after [listener resume]; with [[NSRunLoop currentRunLoop] run];

  3. In your agent/daemon, make sure there's a strong reference to keep your listener's delegate alive. The -[NSXPCListener delegate] property is declared weak, so it's possible that your listener deallocates immediately after you set it. I would put an NSLog statement in the deinit of your delegate's class, just to be sure.