音视频开发:分析一个Gstreamer的插件的Segment Fault

最近的项目中,使用了Gstreamer的rtmpsink来推送RTMP到流媒体服务器,但是总是遇到奇怪的段错误,读了一下rtmpsink的源码。发现虽然有问题,但是可能会有编码上的问题,但是还不至于有段错误。

于是,觉得有可能是rtmpsink使用的librtmp库的问题。

coredump

使用

coredumpctl gdb

这里记录一下,coredumpctl这个命令。

coredumpctl使用list可以显示崩溃的coredump的列表,之后使用gdb加载的时候,可以直接通过PID来加载指定的coredump。

如,我们执行

coredumpctl list

返回了:

Wed 2024-12-18 15:11:31 CST  1422072     0     0  11 present   /bin/bash  
Wed 2024-12-18 16:46:17 CST  1427297     0     0  11 present   /bin/bash  
Wed 2024-12-18 17:20:12 CST  1429745     0     0  11 present   /bin/bash  
Wed 2024-12-18 17:31:28 CST  1430341     0     0  11 present   /bin/ls  
Wed 2024-12-18 18:35:07 CST  1438184     0     0  11 present   /bin/yes  
Thu 2024-12-19 09:14:29 CST  1477445     0     0  11 present   /bin/bash

,其中第一列是时间,第二列(CST之后)那列,就是PID号。

比如我们这时候执行:

coredumpctl gdb 1429745

,就可以把12月18号晚上五点二十那次崩溃的coredump加载进来。

librtmp

我们加载了gstreamer应用的coredump,之后通过gdb的bt命令,看到了崩溃的函数位于librtmp.so的RTMP_Write函数里面。

因为默认安装的librtmp没有安装debug-info,所以通过debuginfo-install librtmp来安装,之后就可以看到具体的调试信息。

安装之后,我们再次加载,通过bt查看堆栈,就看到了具体信息:

Program terminated with signal SIGSEGV, Segmentation fault.
--Type <RET> for more, q to quit, c to continue without paging--
#0  0x00007f646a400489 in ?? () from /usr/lib64/libc.so.6
[Current thread is 1 (LWP 1477490)]
(gdb) bt
#0  0x00007f646a400489 in  () at /usr/lib64/libc.so.6
#1  0x00007f646803ac00 in RTMP_Write
    (r=0x11c4000, buf=0x7f64540849d5 "\353Lu\251\215\236}D^M\253<@3\005\005\003{\036", <incomplete sequence \346>, size=65507) at rtmp.c:5165
#2  0x00007f6469acd36c in gst_rtmp_sink_render (bsink=0x11b5880, buf=0x7f645403d360) at gstrtmpsink.c:271
#3  0x00007f64699f60ee in  () at /usr/lib64/libgstbase-1.0.so.0
#4  0x00007f64699f6e60 in  () at /usr/lib64/libgstbase-1.0.so.0
#5  0x00007f6469f3f21b in  () at /usr/lib64/libgstreamer-1.0.so.0
#6  0x00007f6469f47343 in gst_pad_push () at /usr/lib64/libgstreamer-1.0.so.0
#7  0x00007f64690862a9 in  () at /usr/lib64/gstreamer-1.0/libgstcoreelements.so
#8  0x00007f6469f3f21b in  () at /usr/lib64/libgstreamer-1.0.so.0

此时,我们输入f 1,进入RTMP_Write的栈帧,得到了:

(gdb) f 1
#1  0x00007f646803ac00 in RTMP_Write (r=0x11c4000, 
    buf=0x7f64540849d5 "\353Lu\251\215\236}D^M\253<@3\005\005\003{\036", <incomplete sequence \346>, 
    size=65507) at rtmp.c:5165
5165          memcpy(enc, buf, num);
(gdb) 

看到这里,很明显这几个参数有内存越界了,所以我们打印变量值验证:

(gdb) f 1
#1  0x00007f646803ac00 in RTMP_Write (r=0x11c4000, 
    buf=0x7f64540849d5 "\353Lu\251\215\236}D^M\253<@3\005\005\003{\036", <incomplete sequence \346>, 
    size=65507) at rtmp.c:5165
5165          memcpy(enc, buf, num);
(gdb) p enc
$1 = 0x7f6454028bd2 ""
(gdb) p buf
$2 = 0x7f64540849d5 "\353Lu\251\215\236}D^M\253<@3\005\005\003{\036", <incomplete sequence \346>
(gdb) p num
$3 = -2
(gdb) 

num竟然是-2。

我们显示一下当前的源代码,看看这个-2是怎么来的。

(gdb) p num
$3 = -2
(gdb) l
5160              enc = pkt->m_body + pkt->m_nBytesRead;
5161            }
5162          num = pkt->m_nBodySize - pkt->m_nBytesRead;
5163          if (num > s2)
5164            num = s2;
5165          memcpy(enc, buf, num);
5166          pkt->m_nBytesRead += num;
5167          s2 -= num;
5168          buf += num;
5169          if (pkt->m_nBytesRead == pkt->m_nBodySize)
(gdb) p s2
$4 = -2
(gdb) 

原来,s2就是-2了。

而具体这个s2为什么会变成-2,就可以通过源码看一下了。

我们打开这个版本的librtmp的源码,找到RTMP_Write函数的实现:

  1 int
  2 RTMP_Write(RTMP *r, const char *buf, int size)
  3 {
   
  4   RTMPPacket *pkt = &r->m_write;
  5   char *pend, *enc
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值