之前已经写过2篇博客分析这个问题
https://blog.csdn.net/iyaosan/article/details/132115154
https://smartivr.blog.csdn.net/article/details/132093913
最近一个客户使用顶顶通空号识别 ,对接方式为 vos1->freeswitch(内含空号识别模块)->vos2
每天晚上呼叫结束,通过 status 命令,都可以看到几个无法释放的通道。
客户硬件配置为 24核心 48线程, cps为1000-2000, 3000多并发,因为1个进一个出,所以freeswitch实际上是6000多个通道。
通过调用堆栈分析,得出bridge函数 是2个通道2个线程,线程1 读取通道1的媒体写入通道2,线程2是读取通道2的媒体写入通道1。根据之前的分析,多个线程操作一个通道就有出现死锁的概率,因为fs的switch_core_session_read_frame和switch_core_session_write_frame的实现存在死锁的可能。
具体可以 我提的这个issues
https://github.com/signalwire/freeswitch/issues/2290
刚开始我想,只需要把 session->codec_write_mutex 和 session->codec_read_mutex 公用一个锁就可以避免,经一天线上测试,还是出现了。
经过数天的思考和反复分析最后成功找出解决方法 ,
就是把 switch_core_session_read_frame和switch_core_session_write_frame里面同步消息改成异步消息switch_core_session_queue_message。
c
//switch_core_session_message_t msg = { 0 };
//msg.message_id = SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY;
//switch_core_session_receive_message(session, &msg);
switch_core_session_message_t *msg = switch_core_session_alloc(session, sizeof(*msg));
msg->message_id = SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY;
MESSAGE_STAMP_FFL(msg);
switch_core_session_queue_message(session, msg);
经过数天线上运行,没再出现卡通道问题,也没其他副作用。
至此这个问题最终完美解决。
我之前多次给官方推送pr, 只有2019年之前官方会合并,自从把官方把代码库改用github之后多次提交pr,从未给合并过,这次也不报希望。但是pr推送一个。
https://github.com/signalwire/freeswitch/pull/2300
再解决这个问题过程,多次和杜老师探讨,在此感谢杜老师!