xcode9nsxpcconnection

NSXPCConnection debugging interruption/invalidation


I am on XCode 9, OSX not iOS, Objective-C.

I have an XPC Service to talk to other applications. XPC Services are completely new to me. I've read documentation and articles i found - still i'd need some help.

// NSXPC Connection stored as ivar
self.bridgeagent = [[NSXPCConnection alloc] initWithServiceName:@"com.myid.myapp.bridgeagent"];
self.bridgeagent.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(bridgeagentProtocol)];
self.bridgeagent.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(bridgeagentProxyProtocol)];
self.bridgeagent.exportedObject = self;

[self.bridgeagent setInvalidationHandler:^{
    NSLog(@"Bridgeagent invalidation handler!");
}];

[self.bridgeagent setInterruptionHandler:^{
    NSLog(@"Bridgeagent interruption handler!");
}];

[self.bridgeagent resume];

The Service is called like this:

// openFile method is listed in corresponding protocol
[[self.bridgeagent remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) {
NSLog(@"bridgeagent.openFile errorHandler: %@",error);
}] openFile:parameters withReply:^(NSDictionary *returnParameters) { // do something with result }];

The call works and the service does its job. However - now that the service works i want to dig into making it more stable (even if i don't face any issues right now).

Can someone explain to me

  1. the difference between interruption and invalidation (don't get it when one or the other happens)
  2. if there's a best practice to handle both cases
  3. how to force both cases (for debugging)

Thank you for help


Solution

  • Answer to question 1:

    [self.xpcConnection setInterruptionHandler:^{
        // Connection interrupted. Backend (service) may have crashed.
        // connection used to work but suddenly terminated
    }];
    
    [self.xpcConnection setInvalidationHandler:^{
        // No one is listening. Is the backend running?
        // connection cannot be established
    }];
    

    Answer to question 3:

    interruption: make backend exit in the middle of a transaction (just before reply is sent)

    invalidation: don't start backend (service) at all

    Answer to question 2:

    I have heard that in case "interruption" you should try to reestablish the connection. This can be useful when your service is a launch agent which gets restarted by launchd in case it crashed.

    Actually in my program I don't act upon these cases but simply issue a warning message to the command line. My frontend is a cli program. Alternatively you could log this warning in a logfile, for example with syslog. See 'man 3 syslog'. In my app I use my own logfile with configurable verbosity AND syslog.

    kind regards,

    Robert