2012-10-10 1 views
1

Je suis confronté à un problème de délai bizarre concernant l'envoi/réception de messages via les ports mach. Le concept de base de ma mise en œuvre est la suivante:Bizarre CFMessagePort

Plugin crée le port local → lance processus à distance qui envoie un message au dit port → renvoie les données reçues.

Voici la partie plugin:

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 
} 

Et la partie importante du code de someExecutable est le suivant:

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

Le message du processus à distance est envoyé gracieusement, mais la le rappel est appelé après le processus est terminé et le portRet() a renvoyé une valeur nulle. Si j'invalide le port dans la fonction portRet(), le message n'est jamais reçu.

Je ne peux pas comprendre la raison pour laquelle ce retard se produit. Ce que je veux accomplir est d'obtenir le rappel de port appelé avant les retours portRet(). J'ai aussi essayé d'utiliser la principale file d'attente d'envoi au lieu d'un CFRunLoopSource pour la planification de rappel du port:

CFMessagePortSetDispatchQueue(port, dispatch_get_main_queue()); 

Mais le résultat est à peu près la même chose. Je ne suis pas sûr de ce que je fais mal. Votre aide est grandement appréciée.

Répondre

0

Vous devez exécuter votre boucle d'exécution au portRet jusqu'à ce que le second processus renvoie une valeur. Par exemple:

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