注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

gmd20的个人空间

// 编程和生活

 
 
 

日志

 
 

freeDiameter检测到socket连接错误时的消息处理流程和死锁问题  

2013-11-12 12:32:10|  分类: 程序设计 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
1. fd_cnx_s_recv  /fd_cnx_s_sendv 等函数里面的socket API返回错误,
       通过 fd_cnx_markerror 通知状态机线程
              fd_cnx_addstate(conn, CC_STATUS_ERROR);
              fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_ERROR

2. out_thr 在do_send (fd_cnx_s_sendv )返回之后,得到错误,
     把所有还没有发送出去的消息 , 还在peer->p_tosend 队列里面的,移到 peer->p_tofailover, 队列。

3. 在状态机线程里面,p_psm_th 收到 第一步发过来的 FDEVP_CNX_ERROR错误通知,改变peer的状态并且,把没发送出去的消息进行重新放到

fd_g_outgoing队列,重新路由处理。
   fd_psm_change_state ->leave_open_state-> fd_peer_failover_msg
   在 fd_peer_failover_msg 会把eer->p_tosend 和  peer->p_tofailover里面消息, 重新加到fd_g_outgoing 进行处理。

   稍后会进行peer connection的重连。

4. msg_rt_out线程处理fd_g_outgoing 队列里面消息
    1). 发现peer状态不对,没有其他peer路径可以到达, 发送不出去,通过return_error生成DIAMETER_UNABLE_TO_DELIVER
    2) 如果 第2步消息过来到这里,第3步还没有执行,那么这里消息会再次被加入peer->p_tosend 队列, 消息会在稍后的第3步重新再被放

回fd_g_outgoing。


可能出现的问题。
fd_fifo_post导致的线程阻塞,fd_g_outgoing  和 p_tosend 这几个队列的最大长度限制比较小,如果fd_cnx_s_recv  /fd_cnx_s_sendv函数

的socket调用被长时间阻塞(tcp 死连接),那么p_psm_th   msg_rt_out等线程会被连环阻塞在这个队列操作上面。导致进程全部被锁死。
我们在freeDiameter 1.1.6时候发现这个问题。


freeDiameter 1.2版本代码看到他们通过引入fd_fifo_post_noblock函数,和设置“socket调用超时”来尝试解决这个问题了。

/* Set the timeout option on the socket */
void fd_cnx_s_setto(int sock) 
{
struct timeval tv;
/* Set a timeout on the socket so that in any case we are not stuck waiting for something */
memset(&tv, 0, sizeof(tv));
tv.tv_usec = 100000L;   /* 100ms, to react quickly to head-of-the-line blocking. */ 
  CHECK_SYS_DO( setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)), ); 
  CHECK_SYS_DO( setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)), ); 
}


这样, socket上面的recv 和 send操作就不会阻塞很久。它重复1秒,如果发送不出数据包就会当作网络错误,进行peer状态重置和重建连接


但我觉得,还有有一种竞争导致线程死锁的可能,如果第1 第2步里面清空队列操作之后,msg_rt_out比p_psm_th 线程先抢到队列锁,然后又

把队列塞满导致锁定,其他线程又把msg_rt_out的fd_g_outgoing 队列给塞满了,   那么p_psm_th 线程还是会被一直阻塞,发现不了第一步

发送过来的FDEVP_CNX_ERROR error,加上 socket的out_thr  和 recv 线程这时已经退出,没人再处理peer->p_tosend 队列里面的消息  还

是会一直阻塞下去。

所以p_psm_th线程里面调用fd_p_dw_timeout ->send_DWR函数时绝对不能被阻塞才行。看来还是要给他们反馈这个问题。








  评论这张
 
阅读(435)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017