前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >FreeSWITCH Bug修复一例

FreeSWITCH Bug修复一例

作者头像
Seven Du
发布2020-12-21 14:23:42
1.7K0
发布2020-12-21 14:23:42
举报

好多人都问FreeSWITCH崩溃如何调试,昨天,我正好遇到一个崩溃的情况,很快就找到原因并修复了,简单记录一下,供大家参考。

崩溃发生在master版本上。在视频会议中,当试图播放一个PDF文件时崩溃:

conference 3000 play /tmp/test.pdf

PDF文件支持用到了mod_imagic模块。该模块是我写的,以前是好的,现在出现了崩溃,说明遇到了意外的情况。

我接下来试了PNG文件:

conference 3000 play /tmp/test.png

一样的崩溃。

PDF文件支持是在mod_png中。接着,我试了类似的MP4文件:

conference 3000 play /tmp/test.mp4

MP4不崩溃。

MP4文件在mod_vlc和mod_av中都有支持,我仅试了mod_av。

异同点:mod_imagick和mod_png崩溃,mod_av正常。

conference play 用到了File Interface接口,初步断该接口在mod_av中实现是正确的,而在其它两个模块中有问题。

该文件接口除了可以在conference中调用外,也可以直接用playback,因而,我试了:

<action application=“playback” data=“/tmp/test.pdf”/>

<action application=“playback” data=“/tmp/test.png”/>

<action application=“playback” data=“/tmp/test.mp4”/>

播放都正常,不崩溃。因而,问题缩小为仅在conference中使用该文件接口时崩溃。

好了,挂上lldb(我在Mac上使用llvm,相当于Linux上的gdb和gcc)

ps aux | grep freeswitch #找到FreeSWITCH进程号

lldb

lldb> attach 30918 # FreeSWITCH进程号

continue #继续

重新尝试conference 3000 play /tmp/test.pdf,系统崩溃,看lldb中显示以下消息:

Process 30918 stopped

* thread #36: tid = 0xb53e6, 0x00000001061b5a6b mod_imagick.so`imagick_file_read_video(handle=<unavailable>, frame=0x0000000000000000, flags=<unavailable>) + 987 at mod_imagick.c:317, stop reason = EXC_BAD_ACCESS (code=1, address=0x70)

frame #0: 0x00000001061b5a6b mod_imagick.so`imagick_file_read_video(handle=<unavailable>, frame=0x0000000000000000, flags=<unavailable>) + 987 at mod_imagick.c:317

314

315 if ((context->reads++ % 20) == 0) {

316 switch_img_copy(context->img, &dup);

-> 317 frame->img = dup;

318 context->sent++;

319 } else {

320 if ((flags && SVR_BLOCK)) {

从上面的消息看在执行到mod_imagick.c的317行出错。尝试打印更详细的信息

(lldb) print frame->img

error: Couldn't apply expression side effects : Couldn't dematerialize a result variable: couldn't read its memory

(lldb) print frame

(switch_frame_t *) $2 = 0x0000000000000000

显示frame的值是NULL空指针。其实这一步不是必须的,因为在出错信息的第一行已经显示了frame是NULL了。检查了imagick_file_read_video函数,发现并没有处理frame为NULL的情况。那么,frame为什么是NULL了呢?为什么以前是好用的呢?继续跟踪,输入bt(back trace)看一下调用栈:

(lldb) bt

* thread #36: tid = 0xb53e6, 0x00000001061b5a6b mod_imagick.so`imagick_file_read_video(handle=<unavailable>, frame=0x0000000000000000, flags=<unavailable>) + 987 at mod_imagick.c:317, stop reason = EXC_BAD_ACCESS (code=1, address=0x70)

* frame #0: 0x00000001061b5a6b mod_imagick.so`imagick_file_read_video(handle=<unavailable>, frame=0x0000000000000000, flags=<unavailable>) + 987 at mod_imagick.c:317

frame #1: 0x0000000100c41cec libfreeswitch.1.dylib`switch_core_file_read_video(fh=<unavailable>, frame=<unavailable>, flags=<unavailable>) + 44 at switch_core_file.c:588

frame #2: 0x00000001036c312f mod_conference.so`fnode_check_video(conference=0x00007fd43b847f20, fnode=0x00007fd43b10e320) + 47 at mod_conference.c:1937

frame #3: 0x00000001036be83d

配合源代码逐一检查每一层调用,发现在fnode_check_video函数中(mod_conference.c:1937行)有如下调用

switch_core_file_read_video(&fnode->fh, NULL, SVR_CHECK)

该函数调用的第二个参数就是我们要的frame,而在调用时就直接传入了NULL指针。由于在mod_imagick中没有考虑frame是NULL的情况,因而出现崩溃。

问题是,既然以前没有处理NULL的情况一切都是正常的,说明是上面传入NULL的调用是后来又加上的。

果然,通过检查mod_conference.c的修改历史,发现在385a3b5这次提交中增加了该函数调用,并且,修改时仅修改了mod_av和mod_vlc,在里面加入了一项检查:

if ((flags & SVR_CHECK)) {

return SWITCH_STATUS_BREAK;

}

而类似的检查函数并没有加到mod_imagick和mod_png中。因而导致调用时出错。

在上面的检查中,SVR_CHECK是原函数调用的第三个参数,在调用时仅检查了该标志值,而没有检查frame是否是NULL。因而,我们仅通过阅读代码不容易找到其中的关联性。所幸,这块代码加入的时间不长,我们很快就找到了对应的修改发现了其中的问题。

我把这段代码块也同样加入到了mod_imagick和mod_png中,就不再崩溃了。修复的代码可以通过点击「阅读原文」查看。

类似这样的例子对你有用吗?

别忘点赞 :) 。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2015-07-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FreeSWITCH中文社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档