NSXPC

I have another NSXPC problem, and the problem goes like this

  1. NSXPC server implements an interface -(void) callbackWithInfo:(NSDictionary*)log reply:(void (^)(bool))action;
  2. 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.

Using a Dispatch semaphore to turn an asynchronous call into a synchronous call is generally considered bad form. That’s because the semaphore can’t propagate priority. That’s why we have -synchronousRemoteObjectProxyWithErrorHandler:.

I’m not sure what you’re using the Dispatch global concurrency queue for here, but it’s also bad form. See Avoid Dispatch Global Concurrent Queue.

Polling for completion like this is problematic because, if the server isn’t calling the reply block, those are going to stack up somewhere. I’d have to analysis this in more depth to know for sure what happens, but I think it’ll yield unbounded memory growth on both the client and the server.

Having said all that, this is confusing:

If the action callback is not invoked on the server, the number of FDS on the client increases.

Are you sure it’s file descriptors that are leaking here? I can’t see any file descriptors involved at all. What does lsof say?

OTOH, I don’t think that actually matters too much. You need to stop using this pattern. It’s hard to say what pattern you should use, but if you can post more big picture details I’d be happy to wade in.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Using a Dispatch semaphore to turn an asynchronous call into a synchronous call is generally considered bad form. That’s because the semaphore can’t propagate priority. That’s why we have -synchronousRemoteObjectProxyWithErrorHandler:.

In the code serverProxy for synchronousRemoteObjectProxyWithErrorHandler access object

  1. The use of dispatch_async is to implement an asynchronous operation, and implement the corresponding timeout operation, to be precise, I should be required here to drop a serial column, the reason is because I found the line of sight NSXPC interface call timeout mode is like this.

  2. On the server side does not trigger the callback, the awareness is that the client side calls callbackWithInfo:info reply:^(bool action) and waits for the server side to call the action to implement the callback, but if the server side does not call the action all the time, That leads to more and more fds.

I'm sure that if the NSXPC server side does not call the action callback function, the number of ports on the client side will increase. When the nsxpc server started returning the corresponding action callback function, the number of port numbers in the client program decreased significantly

NSXPC
 
 
Q