Chinaunix首页 | 论坛 | 博客
  • 博客访问: 313512
  • 博文数量: 66
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 509
  • 用 户 组: 普通用户
  • 注册时间: 2015-04-29 13:56
文章分类
文章存档

2018年(2)

2017年(6)

2016年(34)

2015年(24)

我的朋友

分类: LINUX

2016-02-01 14:03:32

最近代码里面测试发现一个问题,在c/s通信机制中,某个命令的应答,出现结果不一致现象
比如client给server发送 命令'test',  期望server应答 "test OK“, 但是在server应答结果中,会出现如下现象:
连续输入多次test命令,有时候会在第5次时候,server应答timeout, 有时候第10次,有时候第2次, 然后接下来再输入,
命令也正常响应"test OK"

在代码里面加打印,并编译debug版本,打印显示 server在给client回应答的时候,应答消息队列的OID值不正确,这个值会
觉得server是否判断超时,这个值正确的时候,server会应答"test OK", 错误时候,server会应答timeout.

在代码里面加打印,发现 添加打印会 影响多线程的时序,最明显的现象是,在代码的特定位置加上了Printf打印OID的值,错误
问题就消失了,支持测试,10次内必会出现一次timeout, 加上打印后30次都没有出现timeout现象, 应答都正常。把打印注释掉
后,timeout问题又出现了。

前面的调试明确的显示了OID的值被修改了,于是理清思路,检查代码里面哪些位置会修改OID的值,发现只有2处,一处是server收到
client应答,添加命令到队列,并创建应答节点,另一处是server在收到子卡模块的处理结果后,更新应答内容到消息队列,并返回给client.
而这2处代码是2个线程,我只在第一处创建队列的位置加了lock, 而在第二处取队列的位置没有加锁, 这样会导致 程序出现某些奇怪的冲突,
取决于代码的执行流程,比如在 创建队列开始时候,取线程开始执行,或者在创建队列函数中间时候,取线程开始执行, 又或者创建队列节点
完成时候,取线程开始执行,这3中情况,现象都会不一致
前一种情况,程序会等待队列有节点在取内容,应答,第二中情况, 程序会应答程序会应答timeout, 因为取到的队列信息只有一部分,
 后一种程序会应答testok。 

原来取节点代码如下:
Oid = MsgQueue->MsgBuf[Cur].MsgOid;
if (Oid == UPG_ALL_OID)  
{
    IsResponseArrived = __IsCurrentResponseReady(UPGD_RETRY_TIMES);
}
else
{
    IsResponseArrived = __IsCurrentResponseReady( RETRY_TIMES);
}

修改后如下:
pthread_mutex_lock(&(MutexLock));
Oid = MsgQueue->MsgBuf[Cur].MsgOid;  // 加了lock判断后,就变成了原子操作,不会出现第2种情况
pthread_mutex_unlock(&(tMutexLock));

if (Oid == UPG_ALL_OID)  
{
    IsResponseArrived = __IsCurrentResponseReady(UPGD_RETRY_TIMES);
}
else

    IsResponseArrived = __IsCurrentResponseReady( RETRY_TIMES); 
}


阅读(1414) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~