XPC to XPC Communication

1.8k Views Asked by At

I am working on an application where i have separated out two different XPC services from the main application. I want a XPC service to communicate with other XPC service which will do some processing and will return the data back to first service and that first service will do its own processing and then will give data back to the main application. I even tried this but communicating between the services give error that "could not communicate with helper application".

My question is that either this is possible or not? If yes that what is required?

Any help would be appreciated.

2

There are 2 best solutions below

0
On

Yes, this is possible, but not at all obvious. I asked questions about this exact thing on and off for a year before an obscure hint from an Apple engineer led me to stumble across the answer.

The trick is that you need to transfer the NSXPCListenerEndpoint of one process to another process. That second process can then use that endpoint object to create a direct connection with the first process. The catch is that, while NSXPCListenerEndpoint is NSCoding compliant, it can only be encoded through an existing XPC connection, which makes this problem sound like a catch-22 (you can't transfer the endpoint until you've created a connection, and you can't create a connection until you have the endpoint).

The solution ("trick") is you need an intermediating process (let's call it "cornerstone") that already has an XPC connections that can exchange endpoints between the other two processes.

In my application I ended up creating a daemon process which acts as my cornerstone, but I think you could do it directly in your application. Here's what you need to do:

  1. Create an application with two XPC services, "A" and "B"
  2. In "A" get the listener object for the process: either get the service listener created automatically (listener = NSXPCListener.serviceListener) or create a dedicated, anonymous, listener for the second process (using listener = NSXPCListener.anonymousListener).
  3. Get the endpoint of the listener (listener.endpoint)
  4. The application should ask "A" for its endpoint.
  5. The application can then launch "B" and, using XPC again, pass the endpoint it got from "A" to "B".
  6. "B" can now use the endpoint object it obtained from "A" (via the application) to create a direct connection to "A" using [[NSXPCConnection alloc] initWithListenerEndpoint:aEndpoint]].
1
On

So I have found that two processes are inevitably going to be unable to communicate to the same XPCService. That is because if you try to launch an XPCService, it will be a unique process to the launcher. And as far as I can tell, you can only communicate with an XPCService that your process launched.

So I believe your second XPCService will be unable to "launch" the first XPCService, and therefore will be unable to communicate with it.

The best you can probably do is have your second XPCService communicate back to your main application process, which then communicates to the first XPCService.

You could do something like:

   [[self.firstXPCConnection remoteObjectProxy] getSomeString:^(NSString *myString) {
        [[self.secondXPCConnection remoteObjectProxy] passSomeString:myString];
   }];

Though disclaimer, I haven't tried this. But the best I can help you with the knowledge I have