【问题标题】:CFMessagePort weirdnessCFMessagePort 怪异
【发布时间】:2012-10-10 18:08:04
【问题描述】:

关于通过 mach 端口发送/接收消息,我遇到了一个奇怪的延迟问题。 我的实现的基本概念如下:

插件创建本地端口→启动远程进程,该进程发送一个 向所述端口发送消息→返回接收到的数据。

这是插件部分:

static NSArray *returned=nil;
static CFDataRef handle_port (
   CFMessagePortRef local,
   SInt32 msgid,
   CFDataRef d,
   void *info
) {
    NSPropertyListFormat format;
    NSDictionary* ret = [NSPropertyListSerialization propertyListWithData:(NSData*)d
                                            options: NSPropertyListImmutable
                                            format: &format
                                            error: nil];
    returned=[NSArray arrayWithArray:[ret objectForKey:@"aKey"]]; //this is what I want returned from the portRet()
    NSLog(@"returned array %@",returned); 
    return NULL;     
}

NSArray* portRet(){
    CFMessagePortRef port = CFMessagePortCreateLocal(kCFAllocatorDefault, CFSTR("com.someport"), handle_port, NULL, NULL);
    CFRunLoopSourceRef source =  CFMessagePortCreateRunLoopSource(kCFAllocatorDefault, port, 0);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes);
    CFRelease(source);
    int r=system("/path/someExecutable"); 
    if(r !=0) NSLog(@"Program error");
    //CFMessagePortInvalidate(port);    
    //CFRelease(port);
    return returned; // always returns nil
}

而someExecutable的代码的重要部分如下:

int main(){
...
CFMessagePortRef port = CFMessagePortCreateRemote(NULL, CFSTR("com.someport"));
    if(port == NULL) exit(1);
    CFDataRef d=CFPropertyListCreateData(kCFAllocatorDefault,[NSDictionary dictionaryWithObject:anArray forKey:@"aKey"], kCFPropertyListXMLFormat_v1_0, 0, NULL);
    CFMessagePortSendRequest (port, 0, d, 0, 0, NULL, NULL);
    NSLog(@"Program is about to exit");
    CFRelease(d);
...
    exit(0);
}

来自远程进程的消息被正常发送,但是在进程结束并且portRet() 返回一个空值之后调用回调。 如果我在portRet() 函数中使端口无效,则永远不会收到消息。

我无法弄清楚发生这种延迟的原因。我想要实现的是在portRet() 返回之前调用端口回调。我还尝试使用主调度队列而不是 CFRunLoopSource 来进行端口的回调调度:

 CFMessagePortSetDispatchQueue(port, dispatch_get_main_queue());

但结果几乎相同。我不确定我做错了什么。 非常感谢您的帮助。

【问题讨论】:

    标签: objective-c ipc port core-foundation mach


    【解决方案1】:

    您需要在portRet 中运行您的运行循环,直到第二个进程返回一个值。例如:

    SInt32 runLoopRunReturnValue = CFRunLoopRunInMode(kCFRunLoopDefaultMode, CFDateGetTimeIntervalSinceDate((__bridge CFDateRef)[NSDate distantFuture], (__bridge CFDateRef)[NSDate date]), true);
    
    if (runLoopRunReturnValue == kCFRunLoopRunHandledSource)
        return returned;
    else {
        // Throw exception or whatever
        // (although this will never be called using the above implementation
        // since [NSDate distantFuture] is wayy into the future...)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-28
      • 2014-09-17
      • 2010-10-12
      • 2012-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多