I have small integration test that is confirming behavior in XPC communications (leveraging NSXPCConnection) between a dummy XPC service and an XPC client. My test is flaky, which is indicating to me that I don't fully understand the nature of connections between services and clients, and I was hoping to get clarity as to what's happening in my test.
My test involves the following steps.
XCode Pre-Action: Load the plist for a dummy XPC service into launchctl.
Create 2 XPC client objects (in the same client process), each with their own NSXPCConnection to the dummy service, and connect.
Tell client 1 to disconnect, which calls NSXPCConnection.invalidate()
Using client 2, send a message to the same dummy XPC service over it's own NSXPCConnection object.
Wait for the echo response from the dummy XPC service
XCode Post-Action: Unload the plist for the dummy XPC service from launchctl
func testMultipleConnections() {
let delegate1 = MockClientDelegate()
let delegate2 = MockClientDelegate()
let client1 = XPCMessagingClientFacade(withServiceName: serviceName, andXPCErrorHandler: {error in })
let client2 = XPCMessagingClientFacade(withServiceName: serviceName, andXPCErrorHandler: {error in })
client1.processMessageDelegate = delegate1
client2.processMessageDelegate = delegate2
_ = client1.connect()
_ = client2.connect()
_ = client1.disconnect()
delegate2.expectation = XCTestExpectation(description: "Message received from echo service")
_ = client2.sendMessage(ofMessageType: eMTAction_Uninstall, withData: ["dummy": "data"])
wait(for: [delegate2.expectation!], timeout: timeout)
}
This test sometimes succeeds and sometimes fails. Sometimes, the test expectation at the bottom is fulfilled, and sometimes the timeout is hit. I have tested with excessively long timeouts to rule-out processing-time as as factor.
I am suspecting that calling invalidate() on one NSXPCConnection object is somehow causing a separate connection between the same client and service process to also be invalidated.
Is it even a valid use-case to have multiple NSXPCConnection objects between a single XPC Service and XPC Client?
When NSXPCConnection.invalidate() is called, does it inherently mean nothing can connect and communicate anymore, or is it just for that specific connection?
When invalidate() is called, what does launchctl do to manage that service? Does it shut it down and allow subsequent connection attempts to spool the service up again? Does it prevent from any connections from ever being made again?
Topic:
App & System Services
SubTopic:
Processes & Concurrency
Tags:
XPC
Service Management
Inter-process communication