2

我有以下代码,我尝试在其中创建一个消息端口,用于两个运行循环之间的通信。1个运行循环正在执行而不是pthread,另一个是主运行循环。此功能似乎在许多不同的条件下正常运行,但是,它们都不是所需的条件。

例如,传递 NULL 而不是 kCFRunLoopDefaultMode 可以工作,但不会阻塞。

为sndData和 MessagePortProc 回调(返回 NULL)的返回值传递 kCFRunLoopDefaultMode 和 NULL 数据也按预期工作,唯一的问题是我需要从 MessagePortProc 回调发送和返回数据,因此使用消息端口。

如果使用 kCFRunLoopDefaultMode 并且 MessagePortProc 返回值或 sndData 参数不是 NULL CFMessagePortSendRequest 块并且永远不会返回。MessagePortProc 被调用得很好,它只是永远不会将控制权返回到调用它的位置。没有打印错误消息,没有发生崩溃,它只是坐在那里。

我正在使用从下面概述的小字节数组创建的简单 CFDataRef 用于发送和接收数据作为测试用例。任何一个都会导致概述的行为。

UInt8 bytes[] = { 0, 1 };
CFDataRef sndData = CFDataCreate(kCFAllocatorDefault, bytes, 2);
SInt32 response = CFMessagePortSendRequest(remoteMsgPort, 0, sndData, 1, 1, kCFRunLoopDefaultMode, &rtnData);


CFDataRef MessagePortProc(CFMessagePortRef msgport, SInt32 msgid, CFDataRef data, void *info) {
    CFDataRef retData = NULL;

    ... Processing Done Here ...

    return retData;
}

void StartMessagePortRunLoop() {
    CFMessagePortContext context = {
        .version = 0,
        .info = NULL,
        .retain = NULL,
        .release = NULL,
        .copyDescription = NULL
    };

    localMsgPort = CFMessagePortCreateLocal(kCFAllocatorDefault, CFSTR("TextServiceMessagePort"), MessagePortProc, &context, NULL);
    if (localMsgPort != NULL) {
        sourceMsgPort = CFMessagePortCreateRunLoopSource(kCFAllocatorDefault, localMsgPort, 0);
        CFRunLoopAddSource(CFRunLoopGetMain(), sourceMsgPort, kCFRunLoopDefaultMode);
    }
}

void StopMessagePortRunLoop() {
    if (CFRunLoopContainsSource(CFRunLoopGetMain(), sourceMsgPort, kCFRunLoopDefaultMode)) {
        CFRunLoopRemoveSource(CFRunLoopGetMain(), sourceMsgPort, kCFRunLoopDefaultMode);
        CFRelease(sourceMsgPort);
    }

    CFMessagePortInvalidate(localMsgPort);
    CFRelease(localMsgPort);
}
4

0 回答 0