From ae5450181cb047b6f5228eaa08b919f744ff3328 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 30 Apr 2017 12:03:31 +0800 Subject: [PATCH 1/3] Fix #636, FD leak for requesting empty HTTP stream. 2.0.241 --- README.md | 2 ++ trunk/src/app/srs_app_http_conn.cpp | 13 +++++++++ trunk/src/app/srs_app_http_conn.hpp | 9 +++++- trunk/src/app/srs_app_http_stream.cpp | 19 +++++++++++++ trunk/src/app/srs_app_recv_thread.cpp | 41 +++++++++++++++++++++++++++ trunk/src/app/srs_app_recv_thread.hpp | 26 +++++++++++++++++ trunk/src/core/srs_core.hpp | 2 +- 7 files changed, 110 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8c1f6aad7..61672708a 100755 --- a/README.md +++ b/README.md @@ -337,6 +337,7 @@ Remark: ## History +* v2.0, 2017-04-30, Fix [#636][bug #636], FD leak for requesting empty HTTP stream. 2.0.241 * v2.0, 2017-04-23, Fix [#851][bug #851], HTTP API support number of video frames for FPS. 2.0.240 * v2.0, 2017-04-18, [2.0 release1(2.0.239)][r2.0r1] released. 86515 lines. * v2.0, 2017-04-18, Fix [#848][bug #848], crash at HTTP fast buffer grow. 2.0.239 @@ -1293,6 +1294,7 @@ Winlin [bug #844]: https://github.com/ossrs/srs/issues/844 [bug #848]: https://github.com/ossrs/srs/issues/848 [bug #851]: https://github.com/ossrs/srs/issues/851 +[bug #636]: https://github.com/ossrs/srs/issues/636 [bug #xxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxx [exo #828]: https://github.com/google/ExoPlayer/pull/828 diff --git a/trunk/src/app/srs_app_http_conn.cpp b/trunk/src/app/srs_app_http_conn.cpp index 8341e26d4..3e5a99c42 100644 --- a/trunk/src/app/srs_app_http_conn.cpp +++ b/trunk/src/app/srs_app_http_conn.cpp @@ -1310,6 +1310,19 @@ SrsResponseOnlyHttpConn::~SrsResponseOnlyHttpConn() { } +int SrsResponseOnlyHttpConn::pop_message(ISrsHttpMessage** preq) +{ + int ret = ERROR_SUCCESS; + + SrsStSocket skt(stfd); + + if ((ret = parser->parse_message(&skt, this, preq)) != ERROR_SUCCESS) { + return ret; + } + + return ret; +} + int SrsResponseOnlyHttpConn::on_got_http_message(ISrsHttpMessage* msg) { int ret = ERROR_SUCCESS; diff --git a/trunk/src/app/srs_app_http_conn.hpp b/trunk/src/app/srs_app_http_conn.hpp index 6e2532e1c..a3b4338ee 100644 --- a/trunk/src/app/srs_app_http_conn.hpp +++ b/trunk/src/app/srs_app_http_conn.hpp @@ -390,7 +390,7 @@ private: class SrsHttpConn : public SrsConnection { -private: +protected: SrsHttpParser* parser; ISrsHttpServeMux* http_mux; public: @@ -421,6 +421,13 @@ class SrsResponseOnlyHttpConn : public SrsHttpConn public: SrsResponseOnlyHttpConn(IConnectionManager* cm, st_netfd_t fd, ISrsHttpServeMux* m); virtual ~SrsResponseOnlyHttpConn(); +public: + // Directly read a HTTP request message. + // It's exported for HTTP stream, such as HTTP FLV, only need to write to client when + // serving it, but we need to start a thread to read message to detect whether FD is closed. + // @see https://github.com/ossrs/srs/issues/636#issuecomment-298208427 + // @remark Should only used in HTTP-FLV streaming connection. + virtual int pop_message(ISrsHttpMessage** preq); public: virtual int on_got_http_message(ISrsHttpMessage* msg); }; diff --git a/trunk/src/app/srs_app_http_stream.cpp b/trunk/src/app/srs_app_http_stream.cpp index 0272bcecd..f25852d09 100755 --- a/trunk/src/app/srs_app_http_stream.cpp +++ b/trunk/src/app/srs_app_http_stream.cpp @@ -54,6 +54,7 @@ using namespace std; #include #include #include +#include #endif @@ -535,10 +536,28 @@ int SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) #ifdef SRS_PERF_FAST_FLV_ENCODER SrsFastFlvStreamEncoder* ffe = dynamic_cast(enc); #endif + + // Use receive thread to accept the close event to avoid FD leak. + // @see https://github.com/ossrs/srs/issues/636#issuecomment-298208427 + SrsHttpMessage* hr = dynamic_cast(r); + SrsResponseOnlyHttpConn* hc = dynamic_cast(hr->connection()); + + SrsHttpRecvThread* trd = new SrsHttpRecvThread(hc); + SrsAutoFree(SrsHttpRecvThread, trd); + + if ((ret = trd->start()) != ERROR_SUCCESS) { + srs_error("http: start notify thread failed, ret=%d", ret); + return ret; + } // TODO: free and erase the disabled entry after all related connections is closed. while (entry->enabled) { pprint->elapse(); + + // Whether client closed the FD. + if ((ret = trd->error_code()) != ERROR_SUCCESS) { + return ret; + } // get messages from consumer. // each msg in msgs.msgs must be free, for the SrsMessageArray never free them. diff --git a/trunk/src/app/srs_app_recv_thread.cpp b/trunk/src/app/srs_app_recv_thread.cpp index a61f41f60..b8c8bcfdd 100644 --- a/trunk/src/app/srs_app_recv_thread.cpp +++ b/trunk/src/app/srs_app_recv_thread.cpp @@ -31,6 +31,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include +#include +#include using namespace std; @@ -523,3 +525,42 @@ void SrsPublishRecvThread::set_socket_buffer(int sleep_ms) rtmp->set_recv_buffer(nb_rbuf); } +SrsHttpRecvThread::SrsHttpRecvThread(SrsResponseOnlyHttpConn* c) +{ + conn = c; + error = ERROR_SUCCESS; + trd = new SrsOneCycleThread("http-receive", this); +} + +SrsHttpRecvThread::~SrsHttpRecvThread() +{ + srs_freep(trd); +} + +int SrsHttpRecvThread::start() +{ + return trd->start(); +} + +int SrsHttpRecvThread::error_code() +{ + return error; +} + +int SrsHttpRecvThread::cycle() +{ + int ret = ERROR_SUCCESS; + + while (true) { + ISrsHttpMessage* req = NULL; + SrsAutoFree(ISrsHttpMessage, req); + + if ((ret = conn->pop_message(&req)) != ERROR_SUCCESS) { + error = ret; + break; + } + } + + return ret; +} + diff --git a/trunk/src/app/srs_app_recv_thread.hpp b/trunk/src/app/srs_app_recv_thread.hpp index a9b001b17..92f12dec1 100644 --- a/trunk/src/app/srs_app_recv_thread.hpp +++ b/trunk/src/app/srs_app_recv_thread.hpp @@ -43,6 +43,8 @@ class SrsRtmpConn; class SrsSource; class SrsRequest; class SrsConsumer; +class SrsHttpConn; +class SrsResponseOnlyHttpConn; /** * for the recv thread to handle the message. @@ -215,5 +217,29 @@ private: virtual void set_socket_buffer(int sleep_ms); }; +/** + * The HTTP receive thread, try to read messages util EOF. + * For example, the HTTP FLV serving thread will use the receive thread to break + * when client closed the request, to avoid FD leak. + * @see https://github.com/ossrs/srs/issues/636#issuecomment-298208427 + */ +class SrsHttpRecvThread : public ISrsOneCycleThreadHandler +{ +private: + SrsResponseOnlyHttpConn* conn; + SrsOneCycleThread* trd; + int error; +public: + SrsHttpRecvThread(SrsResponseOnlyHttpConn* c); + virtual ~SrsHttpRecvThread(); +public: + virtual int start(); +public: + virtual int error_code(); +// interface ISrsOneCycleThreadHandler +public: + virtual int cycle(); +}; + #endif diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 765c01b7a..98c89c501 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR 2 #define VERSION_MINOR 0 -#define VERSION_REVISION 240 +#define VERSION_REVISION 241 // generated by configure, only macros. #include From 79e4f9f3a053c261750def52961ab11f1d19b83f Mon Sep 17 00:00:00 2001 From: walkermi <172192667@qq.com> Date: Sun, 30 Apr 2017 12:29:37 +0800 Subject: [PATCH 2/3] fixed compile error when add --log-info (#860) * Update srs_app_server.cpp fixed compile error when add --log-info * Update srs_app_mpegts_udp.cpp fixed compile error when add --log-info --- trunk/src/app/srs_app_mpegts_udp.cpp | 2 +- trunk/src/app/srs_app_server.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/trunk/src/app/srs_app_mpegts_udp.cpp b/trunk/src/app/srs_app_mpegts_udp.cpp index 920c52bea..dd5149698 100644 --- a/trunk/src/app/srs_app_mpegts_udp.cpp +++ b/trunk/src/app/srs_app_mpegts_udp.cpp @@ -412,7 +412,7 @@ int SrsMpegtsOverUdp::on_ts_video(SrsTsMessage* msg, SrsStream* avs) // ibp frame. // TODO: FIXME: we should group all frames to a rtmp/flv message from one ts message. - srs_info("mpegts: demux avc ibp frame size=%d, dts=%d", ibpframe_size, dts); + srs_info("mpegts: demux avc ibp frame size=%d, dts=%d", frame_size, dts); if ((ret = write_h264_ipb_frame(frame, frame_size, dts, pts)) != ERROR_SUCCESS) { return ret; } diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp index 66ce9772d..e56d2042a 100755 --- a/trunk/src/app/srs_app_server.cpp +++ b/trunk/src/app/srs_app_server.cpp @@ -214,9 +214,9 @@ int SrsRtspListener::listen(string i, int p) return ret; } - srs_info("listen thread cid=%d, current_cid=%d, " + srs_info("listen thread, current_cid=%d, " "listen at port=%d, type=%d, fd=%d started success, ep=%s:%d", - pthread->cid(), _srs_context->get_id(), port, type, fd, ip.c_str(), port); + _srs_context->get_id(), port, type, fd, ip.c_str(), port); srs_trace("%s listen at tcp://%s:%d, fd=%d", srs_listener_type2string(type).c_str(), ip.c_str(), port, listener->fd()); @@ -276,9 +276,9 @@ int SrsHttpFlvListener::listen(string i, int p) return ret; } - srs_info("listen thread cid=%d, current_cid=%d, " + srs_info("listen thread, current_cid=%d, " "listen at port=%d, type=%d, fd=%d started success, ep=%s:%d", - pthread->cid(), _srs_context->get_id(), port, type, fd, ip.c_str(), port); + _srs_context->get_id(), port, type, fd, ip.c_str(), port); srs_trace("%s listen at tcp://%s:%d, fd=%d", srs_listener_type2string(type).c_str(), ip.c_str(), port, listener->fd()); From a613eb78c6b89b0c2718ebed3f7b943ed7d5780c Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 1 May 2017 16:39:59 +0800 Subject: [PATCH 3/3] Fix #865, shouldn't remove ts/m3u8 when hls_dispose disabled. 2.0.242 --- README.md | 2 ++ trunk/src/app/srs_app_hls.cpp | 7 +++++++ trunk/src/core/srs_core.hpp | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 61672708a..9f5733021 100755 --- a/README.md +++ b/README.md @@ -337,6 +337,7 @@ Remark: ## History +* v2.0, 2017-05-01, Fix [#865][bug #865], shouldn't remove ts/m3u8 when hls_dispose disabled. 2.0.242 * v2.0, 2017-04-30, Fix [#636][bug #636], FD leak for requesting empty HTTP stream. 2.0.241 * v2.0, 2017-04-23, Fix [#851][bug #851], HTTP API support number of video frames for FPS. 2.0.240 * v2.0, 2017-04-18, [2.0 release1(2.0.239)][r2.0r1] released. 86515 lines. @@ -1295,6 +1296,7 @@ Winlin [bug #848]: https://github.com/ossrs/srs/issues/848 [bug #851]: https://github.com/ossrs/srs/issues/851 [bug #636]: https://github.com/ossrs/srs/issues/636 +[bug #865]: https://github.com/ossrs/srs/issues/865 [bug #xxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxx [exo #828]: https://github.com/google/ExoPlayer/pull/828 diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index 221f6a2fe..78fc5c2ba 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -1161,6 +1161,13 @@ void SrsHls::dispose() on_unpublish(); } + // Ignore when hls_dispose disabled. + // @see https://github.com/ossrs/srs/issues/865 + int hls_dispose = _srs_config->get_hls_dispose(_req->vhost); + if (!hls_dispose) { + return; + } + muxer->dispose(); } diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 98c89c501..0c6fc2b92 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR 2 #define VERSION_MINOR 0 -#define VERSION_REVISION 241 +#define VERSION_REVISION 242 // generated by configure, only macros. #include