ossrs / srs

SRS is a simple, high-efficiency, real-time video server supporting RTMP, WebRTC, HLS, HTTP-FLV, SRT, MPEG-DASH, and GB28181.

Home Page:https://ossrs.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

When enabling edge push-pull streaming in srs3.0.18, a segmentation fault issue occurs.

xialixin opened this issue · comments

After downloading srs3.0.18 and running the test process, when enabling edge push-pull streaming, a segmentation fault problem occurs. The following is the stack information from gdb.
[2017-02-27 15:46:00.823][Trace][26128][105] dispatch cached gop success. count=0, duration=-1
[2017-02-27 15:46:00.824][Trace][26128][105] create consumer, queue_size=30.00, jitter=1
[2017-02-27 15:46:00.824][Trace][26128][105] ignore disabled exec for vhost=defaultVhost
[2017-02-27 15:46:00.834][Trace][26128][105] exec thread cid=108, current_cid=105

Program received signal SIGSEGV, Segmentation fault.
0x00000000004e05ea in SrsTcpClient::get_recv_bytes (this=0x976590) at src/app/srs_app_st.cpp:520
520 return io->get_recv_bytes();
Missing separate debuginfos, use: debuginfo-install glibc-2.17-157.el7_3.1.x86_64 libgcc-4.8.5-11.el7.x86_64 libstdc++-4.8.5-11.el7.x86_64
(gdb) bt
#0 0x00000000004e05ea in SrsTcpClient::get_recv_bytes (this=0x976590) at src/app/srs_app_st.cpp:520
#1 0x0000000000489231 in SrsKbps::set_io (this=0x976270, in=0x9765c0, out=0x9765c0)
at src/protocol/srs_protocol_kbps.cpp:129
#2 0x00000000004abac3 in SrsSimpleRtmpClient::connect (this=0x976220) at src/app/srs_app_rtmp_conn.cpp:112
#3 0x0000000000553ef0 in SrsEdgeRtmpUpstream::connect (this=0x970650, r=0x970e30, lb=0x971570)
at src/app/srs_app_edge.cpp:129
#4 0x000000000055494a in SrsEdgeIngester::cycle (this=0x970600) at src/app/srs_app_edge.cpp:242
#5 0x00000000004db345 in SrsReusableThread2::cycle (this=0x971520) at src/app/srs_app_thread.cpp:315
#6 0x00000000004de72b in internal::SrsThread::thread_cycle (this=0x970ac0) at src/app/srs_app_st.cpp:215
#7 0x00000000004de929 in internal::SrsThread::thread_fun (arg=0x970ac0) at src/app/srs_app_st.cpp:255
#8 0x000000000058c325 in _st_thread_main () at sched.c:337
#9 0x000000000058caad in st_thread_create (start=0xffffffff, arg=0x7ffff7f826f0, joinable=0, stk_size=4096) at sched.c:616
#10 0x0000000000976190 in ?? ()
#11 0x00007ffff7f827d0 in ?? ()
#12 0x000000000058cad1 in st_thread_create (start=0x6d, arg=0x7ffff7f3ae30, joinable=0, stk_size=0) at sched.c:624
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
(gdb)

Based on the stack information, I traced the code and found that the "io" member variable in srs_app_st.cpp is NULL and not assigned, causing a segmentation fault. Analyzing the code, the reason is in srs_app_rtmp_conn.cpp.
int SrsSimpleRtmpClient::connect()
{
int ret = ERROR_SUCCESS;
close();

transport = new SrsTcpClient(req->host, req->port, connect_timeout);
client = new SrsRtmpClient(transport);
kbps->set_io(transport, transport);

if ((ret = transport->connect()) != ERROR_SUCCESS) {
    close();
    return ret;
}
client->set_recv_timeout(stream_timeout);
client->set_send_timeout(stream_timeout);
''''''''

The line 'kbps->set_io(transport, transport);' is calling the value of 'io', and the assignment of 'io' variable is set in 'transport->connect()'.

int SrsTcpClient::connect()
{
int ret = ERROR_SUCCESS;

close();

srs_assert(stfd == NULL);
if ((ret = srs_socket_connect(host, port, timeout, &stfd)) != ERROR_SUCCESS) {
    srs_error("connect tcp://%s:%d failed, to=%"PRId64"ms. ret=%d", host.c_str(), port, timeout, ret);
    return ret;
}

srs_assert(io == NULL);
io = new SrsStSocket(stfd);  

return ret;

} The 'io' was called before it was set. This resulted in using a null value and causing a segmentation fault.
In the test, the code in 'int SrsSimpleRtmpClient::connect()' in 'srs_app_st.cpp' was modified as follows:
int SrsSimpleRtmpClient::connect()
{
int ret = ERROR_SUCCESS;
close();

transport = new SrsTcpClient(req->host, req->port, connect_timeout);

if ((ret = transport->connect()) != ERROR_SUCCESS) {
    close();
    return ret;
}

client = new SrsRtmpClient(transport);
kbps->set_io(transport, transport);

client->set_recv_timeout(stream_timeout);
client->set_send_timeout(stream_timeout);
''''''''

}
After compiling and running, the edge pushing and pulling streams are normal, and there are no more segmentation faults.

TRANS_BY_GPT3

I think it should be changed to the SrsTcpClient class, which should ensure that the interface is available even without a connection.

TRANS_BY_GPT3

I made some changes to SrsTcpClient and also changed it to new-delete mode, so there is no need to close and reuse objects.

o = new SrsTcpClient()
o.connect();
o.read()
o.write()
delete o;

The close method has been removed.

TRANS_BY_GPT3

At the same time, SrsStSocket was changed to an empty constructor, finally understanding why it is necessary to keep the constructor simple.

skt = new SrsStSocket();
skt->initialize(stfd);

A simple empty constructor, and then use the initialize function to set some states.
This allows for adapting to an empty object, so after skt = new SrsStSocket(), it can be called:

skt->get_recv_bytes()

This also makes sense because after constructing this object, it is possible for it to return 0 when asked how many bytes it has received.

TRANS_BY_GPT3