QNX Message Passing,一个让人头秃的 IPC BUG
问题描述
QNX系统中 Client 与 Server 通过 QNX Message Passing 进行进程间通信。正式开发前写的测试Client,和 Server 通信一切正常。但把同样的代码拷贝到最终的 Client 中却发现调用MsgSend()
后无响应,pidin
显示 Client 处于 REPLY PENDING
的状态。
几番尝试,发现一个让人很难接受的事实:只有在 Client 的主线程中调用 MsgSend()
才能收到 Server 的回复,如果在 Client 的对等线程中调用MsgSend()
,则会因为收不到 Server 的回复而 Pending。
问题分析
测试Client能正常工作,所以起初怀疑是正式 Client 的问题,但一直没有进展。甚至曾一度怀疑是否是 QNX 的限制,MsgSend()
只能在主线程中调用,官网文档翻了一圈并没有发现这样的限制。自己写了个 IPC Server 来测试,发现并没有这个问题。
Client | Server | 结果 |
---|---|---|
测试 Client,主线程中调用 MsgSend() |
正式 Server | OK |
正式 Client,对等线程中调用 MsgSend() |
正式 Server | REPLY PENDING |
正式 Client,对等线程中调用 MsgSend() |
测试 Server | OK |
最后不得不怀疑起 Server,莫非 Server 端有什么机制能检测到消息是发自主线程还是对等线程,然后只回复来自主线程的 IPC 请求?
一个典型的 IPC Server 示例代码如下:
While(1) {
int rcvid = MsgReceive(chid, &recvBuf, sizeof(recvBuf), NULL);
/* process request, and reply to unblock the IPC client */
MsgReply(rcvid, EOK, &replyBuf, sizeof(replyBuf));
}
如果是从 Client 的主线程发送来的消息,rcvid
是一个很小的数字,如 1, 3, 5… 如果是从Client 的对等线程发送来的消息,rcvid
是一个大于 65535 的数字,如 65538, 65540, 65542…
让人意外的是正式 Server 用了一个 int16_t
来保存 rcvid
,直接导致后续的 MsgReply()
无法正确地将消息回给 Client,从而导致 Client 一直处于 REPLY PENDING 状态。
Reference
http://www.qnx.com/developers/docs/7.0.0/#com.qnx.doc.neutrino.sys_arch/topic/ipc_Robust.html
本文作者:Zijian/TENG(微信公众号:好记性如烂笔头),转载请注明原文链接:https://www.cnblogs.com/tengzijian/p/qnx-message-passing-ipc-bug-in-peer-thread.html