继续操作前请注册或者登录。
winlin

fix mem leak of encoder, edge and source. add destroy for gmc to detect mem leak. to 0.9.89

@@ -35,26 +35,59 @@ SrsConnection::SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd) @@ -35,26 +35,59 @@ SrsConnection::SrsConnection(SrsServer* srs_server, st_netfd_t client_stfd)
35 server = srs_server; 35 server = srs_server;
36 stfd = client_stfd; 36 stfd = client_stfd;
37 connection_id = 0; 37 connection_id = 0;
  38 + pthread = new SrsThread(this, 0);
38 } 39 }
39 40
40 SrsConnection::~SrsConnection() 41 SrsConnection::~SrsConnection()
41 { 42 {
42 - srs_freepa(ip);  
43 - srs_close_stfd(stfd); 43 + stop();
44 } 44 }
45 45
46 int SrsConnection::start() 46 int SrsConnection::start()
47 { 47 {
  48 + return pthread->start();
  49 +}
  50 +
  51 +int SrsConnection::cycle()
  52 +{
48 int ret = ERROR_SUCCESS; 53 int ret = ERROR_SUCCESS;
49 54
50 - if (st_thread_create(cycle_thread, this, 0, 0) == NULL) {  
51 - ret = ERROR_ST_CREATE_CYCLE_THREAD;  
52 - srs_error("st_thread_create conn cycle thread error. ret=%d", ret);  
53 - return ret; 55 + _srs_context->generate_id();
  56 + connection_id = _srs_context->get_id();
  57 +
  58 + ret = do_cycle();
  59 +
  60 + // if socket io error, set to closed.
  61 + if (srs_is_client_gracefully_close(ret)) {
  62 + ret = ERROR_SOCKET_CLOSED;
54 } 63 }
55 - srs_verbose("create st conn cycle thread success.");  
56 64
57 - return ret; 65 + // success.
  66 + if (ret == ERROR_SUCCESS) {
  67 + srs_trace("client process normally finished. ret=%d", ret);
  68 + }
  69 +
  70 + // client close peer.
  71 + if (ret == ERROR_SOCKET_CLOSED) {
  72 + srs_warn("client disconnect peer. ret=%d", ret);
  73 + }
  74 +
  75 + // set loop to stop to quit.
  76 + pthread->stop_loop();
  77 +
  78 + return ERROR_SUCCESS;
  79 +}
  80 +
  81 +void SrsConnection::on_thread_stop()
  82 +{
  83 + server->remove(this);
  84 +}
  85 +
  86 +void SrsConnection::stop()
  87 +{
  88 + srs_close_stfd(stfd);
  89 + srs_freep(pthread);
  90 + srs_freepa(ip);
58 } 91 }
59 92
60 int SrsConnection::get_peer_ip() 93 int SrsConnection::get_peer_ip()
@@ -92,40 +125,3 @@ int SrsConnection::get_peer_ip() @@ -92,40 +125,3 @@ int SrsConnection::get_peer_ip()
92 return ret; 125 return ret;
93 } 126 }
94 127
95 -void SrsConnection::cycle()  
96 -{  
97 - int ret = ERROR_SUCCESS;  
98 -  
99 - _srs_context->generate_id();  
100 - connection_id = _srs_context->get_id();  
101 -  
102 - ret = do_cycle();  
103 -  
104 - // if socket io error, set to closed.  
105 - if (srs_is_client_gracefully_close(ret)) {  
106 - ret = ERROR_SOCKET_CLOSED;  
107 - }  
108 -  
109 - // success.  
110 - if (ret == ERROR_SUCCESS) {  
111 - srs_trace("client process normally finished. ret=%d", ret);  
112 - }  
113 -  
114 - // client close peer.  
115 - if (ret == ERROR_SOCKET_CLOSED) {  
116 - srs_warn("client disconnect peer. ret=%d", ret);  
117 - }  
118 -  
119 - server->remove(this);  
120 -}  
121 -  
122 -void* SrsConnection::cycle_thread(void* arg)  
123 -{  
124 - SrsConnection* conn = (SrsConnection*)arg;  
125 - srs_assert(conn != NULL);  
126 -  
127 - conn->cycle();  
128 -  
129 - return NULL;  
130 -}  
131 -  
@@ -31,10 +31,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,10 +31,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 #include <srs_core.hpp> 31 #include <srs_core.hpp>
32 32
33 #include <srs_app_st.hpp> 33 #include <srs_app_st.hpp>
  34 +#include <srs_app_thread.hpp>
34 35
35 class SrsServer; 36 class SrsServer;
36 -class SrsConnection 37 +class SrsConnection : public ISrsThreadHandler
37 { 38 {
  39 +private:
  40 + SrsThread* pthread;
38 protected: 41 protected:
39 char* ip; 42 char* ip;
40 SrsServer* server; 43 SrsServer* server;
@@ -45,13 +48,13 @@ public: @@ -45,13 +48,13 @@ public:
45 virtual ~SrsConnection(); 48 virtual ~SrsConnection();
46 public: 49 public:
47 virtual int start(); 50 virtual int start();
  51 + virtual int cycle();
  52 + virtual void on_thread_stop();
48 protected: 53 protected:
49 virtual int do_cycle() = 0; 54 virtual int do_cycle() = 0;
  55 + virtual void stop();
50 protected: 56 protected:
51 virtual int get_peer_ip(); 57 virtual int get_peer_ip();
52 -private:  
53 - virtual void cycle();  
54 - static void* cycle_thread(void* arg);  
55 }; 58 };
56 59
57 #endif 60 #endif
@@ -335,6 +335,9 @@ SrsEdgeForwarder::SrsEdgeForwarder() @@ -335,6 +335,9 @@ SrsEdgeForwarder::SrsEdgeForwarder()
335 SrsEdgeForwarder::~SrsEdgeForwarder() 335 SrsEdgeForwarder::~SrsEdgeForwarder()
336 { 336 {
337 stop(); 337 stop();
  338 +
  339 + srs_freep(pthread);
  340 + srs_freep(queue);
338 } 341 }
339 342
340 void SrsEdgeForwarder::set_queue_size(double queue_size) 343 void SrsEdgeForwarder::set_queue_size(double queue_size)
@@ -53,6 +53,7 @@ SrsEncoder::~SrsEncoder() @@ -53,6 +53,7 @@ SrsEncoder::~SrsEncoder()
53 on_unpublish(); 53 on_unpublish();
54 54
55 srs_freep(pthread); 55 srs_freep(pthread);
  56 + srs_freep(pithy_print);
56 } 57 }
57 58
58 int SrsEncoder::on_publish(SrsRequest* req) 59 int SrsEncoder::on_publish(SrsRequest* req)
@@ -79,6 +79,8 @@ SrsRtmpConn::~SrsRtmpConn() @@ -79,6 +79,8 @@ SrsRtmpConn::~SrsRtmpConn()
79 { 79 {
80 _srs_config->unsubscribe(this); 80 _srs_config->unsubscribe(this);
81 81
  82 + stop();
  83 +
82 srs_freep(req); 84 srs_freep(req);
83 srs_freep(res); 85 srs_freep(res);
84 srs_freep(rtmp); 86 srs_freep(rtmp);
@@ -44,6 +44,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -44,6 +44,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
44 #ifdef SRS_AUTO_INGEST 44 #ifdef SRS_AUTO_INGEST
45 #include <srs_app_ingest.hpp> 45 #include <srs_app_ingest.hpp>
46 #endif 46 #endif
  47 +#include <srs_app_source.hpp>
47 48
48 #define SERVER_LISTEN_BACKLOG 512 49 #define SERVER_LISTEN_BACKLOG 512
49 50
@@ -251,6 +252,13 @@ int SrsSignalManager::start() @@ -251,6 +252,13 @@ int SrsSignalManager::start()
251 sa.sa_flags = 0; 252 sa.sa_flags = 0;
252 sigaction(SIGINT, &sa, NULL); 253 sigaction(SIGINT, &sa, NULL);
253 254
  255 + sa.sa_handler = SrsSignalManager::sig_catcher;
  256 + sigemptyset(&sa.sa_mask);
  257 + sa.sa_flags = 0;
  258 + sigaction(SIGUSR2, &sa, NULL);
  259 +
  260 + srs_trace("signal installed");
  261 +
254 return pthread->start(); 262 return pthread->start();
255 } 263 }
256 264
@@ -316,27 +324,17 @@ SrsServer::~SrsServer() @@ -316,27 +324,17 @@ SrsServer::~SrsServer()
316 324
317 void SrsServer::destroy() 325 void SrsServer::destroy()
318 { 326 {
319 - _srs_config->unsubscribe(this); 327 + srs_warn("start destroy server");
320 328
321 - if (true) {  
322 - std::vector<SrsConnection*>::iterator it;  
323 - for (it = conns.begin(); it != conns.end(); ++it) {  
324 - SrsConnection* conn = *it;  
325 - srs_freep(conn);  
326 - }  
327 - conns.clear();  
328 - } 329 + _srs_config->unsubscribe(this);
329 330
330 close_listeners(SrsListenerRtmpStream); 331 close_listeners(SrsListenerRtmpStream);
331 close_listeners(SrsListenerHttpApi); 332 close_listeners(SrsListenerHttpApi);
332 close_listeners(SrsListenerHttpStream); 333 close_listeners(SrsListenerHttpStream);
333 -  
334 - if (pid_fd > 0) {  
335 - ::close(pid_fd);  
336 - pid_fd = -1;  
337 - }  
338 -  
339 - srs_freep(signal_manager); 334 +
  335 +#ifdef SRS_AUTO_INGEST
  336 + ingester->stop();
  337 +#endif
340 338
341 #ifdef SRS_AUTO_HTTP_API 339 #ifdef SRS_AUTO_HTTP_API
342 srs_freep(http_api_handler); 340 srs_freep(http_api_handler);
@@ -348,6 +346,27 @@ void SrsServer::destroy() @@ -348,6 +346,27 @@ void SrsServer::destroy()
348 #ifdef SRS_AUTO_INGEST 346 #ifdef SRS_AUTO_INGEST
349 srs_freep(ingester); 347 srs_freep(ingester);
350 #endif 348 #endif
  349 +
  350 + if (pid_fd > 0) {
  351 + ::close(pid_fd);
  352 + pid_fd = -1;
  353 + }
  354 +
  355 + srs_freep(signal_manager);
  356 +
  357 + for (std::vector<SrsConnection*>::iterator it = conns.begin(); it != conns.end();) {
  358 + SrsConnection* conn = *it;
  359 +
  360 + // remove the connection, then free it,
  361 + // for the free will remove itself from server,
  362 + // when erased here, the remove of server will ignore.
  363 + it = conns.erase(it);
  364 +
  365 + srs_freep(conn);
  366 + }
  367 + conns.clear();
  368 +
  369 + SrsSource::destroy();
351 } 370 }
352 371
353 int SrsServer::initialize() 372 int SrsServer::initialize()
@@ -540,12 +559,14 @@ int SrsServer::cycle() @@ -540,12 +559,14 @@ int SrsServer::cycle()
540 559
541 ret = do_cycle(); 560 ret = do_cycle();
542 561
543 -#ifdef SRS_AUTO_INGEST  
544 - ingester->stop();  
545 -#endif  
546 -  
547 destroy(); 562 destroy();
548 563
  564 +#ifdef SRS_AUTO_GPERF_MC
  565 + srs_warn("sleep a long time for system st-threads to cleanup.");
  566 + st_usleep(3 * 1000 * 1000);
  567 + srs_warn("system quit");
  568 +#endif
  569 +
549 return ret; 570 return ret;
550 } 571 }
551 572
@@ -553,10 +574,14 @@ void SrsServer::remove(SrsConnection* conn) @@ -553,10 +574,14 @@ void SrsServer::remove(SrsConnection* conn)
553 { 574 {
554 std::vector<SrsConnection*>::iterator it = std::find(conns.begin(), conns.end(), conn); 575 std::vector<SrsConnection*>::iterator it = std::find(conns.begin(), conns.end(), conn);
555 576
556 - if (it != conns.end()) {  
557 - conns.erase(it); 577 + // removed by destroy, ignore.
  578 + if (it == conns.end()) {
  579 + srs_warn("server moved connection, ignore.");
  580 + return;
558 } 581 }
559 582
  583 + conns.erase(it);
  584 +
560 srs_info("conn removed. conns=%d", (int)conns.size()); 585 srs_info("conn removed. conns=%d", (int)conns.size());
561 586
562 // all connections are created by server, 587 // all connections are created by server,
@@ -571,7 +596,7 @@ void SrsServer::on_signal(int signo) @@ -571,7 +596,7 @@ void SrsServer::on_signal(int signo)
571 return; 596 return;
572 } 597 }
573 598
574 - if (signo == SIGINT) { 599 + if (signo == SIGINT || signo == SIGUSR2) {
575 #ifdef SRS_AUTO_GPERF_MC 600 #ifdef SRS_AUTO_GPERF_MC
576 srs_trace("gmc is on, main cycle will terminate normally."); 601 srs_trace("gmc is on, main cycle will terminate normally.");
577 signal_gmc_stop = true; 602 signal_gmc_stop = true;
@@ -611,6 +636,7 @@ int SrsServer::do_cycle() @@ -611,6 +636,7 @@ int SrsServer::do_cycle()
611 // because directly exit will cause core-dump. 636 // because directly exit will cause core-dump.
612 #ifdef SRS_AUTO_GPERF_MC 637 #ifdef SRS_AUTO_GPERF_MC
613 if (signal_gmc_stop) { 638 if (signal_gmc_stop) {
  639 + srs_warn("gmc got singal to stop server.");
614 return ret; 640 return ret;
615 } 641 }
616 #endif 642 #endif
@@ -437,6 +437,16 @@ int SrsSource::find(SrsRequest* req, SrsSource** ppsource) @@ -437,6 +437,16 @@ int SrsSource::find(SrsRequest* req, SrsSource** ppsource)
437 return ret; 437 return ret;
438 } 438 }
439 439
  440 +void SrsSource::destroy()
  441 +{
  442 + std::map<std::string, SrsSource*>::iterator it;
  443 + for (it = pool.begin(); it != pool.end(); ++it) {
  444 + SrsSource* source = it->second;
  445 + srs_freep(source);
  446 + }
  447 + pool.clear();
  448 +}
  449 +
440 SrsSource::SrsSource(SrsRequest* req) 450 SrsSource::SrsSource(SrsRequest* req)
441 { 451 {
442 _req = req->copy(); 452 _req = req->copy();
@@ -468,14 +478,9 @@ SrsSource::~SrsSource() @@ -468,14 +478,9 @@ SrsSource::~SrsSource()
468 { 478 {
469 _srs_config->unsubscribe(this); 479 _srs_config->unsubscribe(this);
470 480
471 - if (true) {  
472 - std::vector<SrsConsumer*>::iterator it;  
473 - for (it = consumers.begin(); it != consumers.end(); ++it) {  
474 - SrsConsumer* consumer = *it;  
475 - srs_freep(consumer);  
476 - }  
477 - consumers.clear();  
478 - } 481 + // never free the consumers,
  482 + // for all consumers are auto free.
  483 + consumers.clear();
479 484
480 if (true) { 485 if (true) {
481 std::vector<SrsForwarder*>::iterator it; 486 std::vector<SrsForwarder*>::iterator it;
@@ -222,6 +222,11 @@ public: @@ -222,6 +222,11 @@ public:
222 * @remark stream_url should without port and schema. 222 * @remark stream_url should without port and schema.
223 */ 223 */
224 static int find(SrsRequest* req, SrsSource** ppsource); 224 static int find(SrsRequest* req, SrsSource** ppsource);
  225 + /**
  226 + * when system exit, destroy the sources,
  227 + * for gmc to analysis mem leaks.
  228 + */
  229 + static void destroy();
225 private: 230 private:
226 // deep copy of client request. 231 // deep copy of client request.
227 SrsRequest* _req; 232 SrsRequest* _req;
@@ -121,6 +121,11 @@ bool SrsThread::can_loop() @@ -121,6 +121,11 @@ bool SrsThread::can_loop()
121 return loop; 121 return loop;
122 } 122 }
123 123
  124 +void SrsThread::stop_loop()
  125 +{
  126 + loop = false;
  127 +}
  128 +
124 void SrsThread::thread_cycle() 129 void SrsThread::thread_cycle()
125 { 130 {
126 int ret = ERROR_SUCCESS; 131 int ret = ERROR_SUCCESS;
@@ -49,19 +49,21 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -49,19 +49,21 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
49 * when thread interrupt, the socket maybe not got EINT, 49 * when thread interrupt, the socket maybe not got EINT,
50 * espectially on st_usleep(), so the cycle must check the loop, 50 * espectially on st_usleep(), so the cycle must check the loop,
51 * when handler->cycle() has loop itself, for example: 51 * when handler->cycle() has loop itself, for example:
52 -* handler->cycle() is:  
53 -* while (true):  
54 -* st_usleep(0);  
55 -* if (read_from_socket(skt) < 0) break; 52 +* while (true):
  53 +* st_usleep(0);
  54 +* if (read_from_socket(skt) < 0) break;
56 * if thread stop when read_from_socket, it's ok, the loop will break, 55 * if thread stop when read_from_socket, it's ok, the loop will break,
57 * but when thread stop interrupt the s_usleep(0), then the loop is 56 * but when thread stop interrupt the s_usleep(0), then the loop is
58 * death loop. 57 * death loop.
59 * in a word, the handler->cycle() must: 58 * in a word, the handler->cycle() must:
60 -* handler->cycle() is:  
61 -* while (pthread->can_loop()):  
62 -* st_usleep(0);  
63 -* if (read_from_socket(skt) < 0) break; 59 +* while (pthread->can_loop()):
  60 +* st_usleep(0);
  61 +* if (read_from_socket(skt) < 0) break;
64 * check the loop, then it works. 62 * check the loop, then it works.
  63 +*
  64 +* in the thread itself, that is the cycle method,
  65 +* if itself want to terminate the thread, should never use stop(),
  66 +* but use stop_loop() to set the loop to false and terminate normally.
65 */ 67 */
66 class ISrsThreadHandler 68 class ISrsThreadHandler
67 { 69 {
@@ -117,12 +119,19 @@ public: @@ -117,12 +119,19 @@ public:
117 * @remark user can stop multiple times, ignore if already stopped. 119 * @remark user can stop multiple times, ignore if already stopped.
118 */ 120 */
119 virtual void stop(); 121 virtual void stop();
  122 +public:
120 /** 123 /**
121 * whether the thread should loop, 124 * whether the thread should loop,
122 * used for handler->cycle() which has a loop method, 125 * used for handler->cycle() which has a loop method,
123 * to check this method, break if false. 126 * to check this method, break if false.
124 */ 127 */
125 virtual bool can_loop(); 128 virtual bool can_loop();
  129 + /**
  130 + * for the loop thread to stop the loop.
  131 + * other thread can directly use stop() to stop loop and wait for quit.
  132 + * this stop loop method only set loop to false.
  133 + */
  134 + virtual void stop_loop();
126 private: 135 private:
127 virtual void thread_cycle(); 136 virtual void thread_cycle();
128 static void* thread_fun(void* arg); 137 static void* thread_fun(void* arg);
@@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 // current release version 31 // current release version
32 #define VERSION_MAJOR "0" 32 #define VERSION_MAJOR "0"
33 #define VERSION_MINOR "9" 33 #define VERSION_MINOR "9"
34 -#define VERSION_REVISION "88" 34 +#define VERSION_REVISION "89"
35 #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION 35 #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
36 // server info. 36 // server info.
37 #define RTMP_SIG_SRS_KEY "srs" 37 #define RTMP_SIG_SRS_KEY "srs"