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

posted @ 2020-06-14 14:37  Zijian/TENG  阅读(458)  评论(0编辑  收藏  举报