1

マッハ ポートを介したメッセージの送受信に関する奇妙な遅延の問題に直面しています。私の実装の基本的な概念は次のとおりです。

プラグインはローカル ポートを作成します → そのポートにメッセージを送信するリモート プロセスを起動します → 受信したデータを返します。

プラグイン部分は次のとおりです。

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);
}

リモート プロセスからのメッセージは正常に送信されますが、プロセスが終了してが null 値を返した後にコールバックが呼び出されます。portRet()関数内でポートを無効にするportRet()と、メッセージが受信されません。

この遅延が発生している理由がわかりません。私が達成したいのは、portRet()戻る前に呼び出されるポート コールバックを取得することです。CFRunLoopSourceまた、ポートのコールバック スケジューリングの代わりに、メインのディスパッチ キューを使用しようとしました。

 CFMessagePortSetDispatchQueue(port, dispatch_get_main_queue());

しかし、結果はほとんど同じです。私が間違っているのかわかりません。よろしくお願いいたします。

4

1 に答える 1

1

portRet2 番目のプロセスが値を返すまで、実行ループを実行する必要があります。例えば:

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...)
}
于 2013-03-29T03:43:33.343 に答える