• 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 结果
    测试程序,主线程中调用 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 the request based on recvBuf … */
       MsgReply(rcvid, EOK, &replyBuf, sizeof(replyBuf)); // reply to unblock the IPC client
    }

    如果是从 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  
  • 相关阅读:
    吴裕雄--天生自然Django框架开发笔记--Django 路由
    吴裕雄--天生自然Django框架开发笔记--Django 视图
    吴裕雄--天生自然Django框架开发笔记--Django 表单
    吴裕雄--天生自然Django框架开发笔记--Django 模型
    Redis07——Redis到底能用在什么地方(下)
    Redis06——Redis到底能用在什么地方(上)
    Redis05——Redis Cluster 如何实现分布式集群
    Redis04——五分钟明白Redis的哨兵模式
    Redis03——Redis是如何删除你的数据的
    Redis02——Redis内存数据如何保存到磁盘
  • 原文地址:https://www.cnblogs.com/tengzijian/p/qnx-message-passing-ipc-bug-in-peer-thread.html
Copyright © 2020-2023  润新知