winlin

fix #374: when terminate srs, cleanup to ensure FFMPEG quit.

@@ -403,6 +403,10 @@ int SrsFFMPEG::start() @@ -403,6 +403,10 @@ int SrsFFMPEG::start()
403 403
404 // child process: ffmpeg encoder engine. 404 // child process: ffmpeg encoder engine.
405 if (pid == 0) { 405 if (pid == 0) {
  406 + // ignore the SIGINT and SIGTERM
  407 + signal(SIGINT, SIG_IGN);
  408 + signal(SIGTERM, SIG_IGN);
  409 +
406 // redirect logs to file. 410 // redirect logs to file.
407 int log_fd = -1; 411 int log_fd = -1;
408 int flags = O_CREAT|O_WRONLY|O_APPEND; 412 int flags = O_CREAT|O_WRONLY|O_APPEND;
@@ -159,6 +159,11 @@ int SrsIngester::parse_engines(SrsConfDirective* vhost, SrsConfDirective* ingest @@ -159,6 +159,11 @@ int SrsIngester::parse_engines(SrsConfDirective* vhost, SrsConfDirective* ingest
159 return ret; 159 return ret;
160 } 160 }
161 161
  162 +void SrsIngester::dispose()
  163 +{
  164 + stop();
  165 +}
  166 +
162 void SrsIngester::stop() 167 void SrsIngester::stop()
163 { 168 {
164 pthread->stop(); 169 pthread->stop();
@@ -70,6 +70,8 @@ public: @@ -70,6 +70,8 @@ public:
70 SrsIngester(); 70 SrsIngester();
71 virtual ~SrsIngester(); 71 virtual ~SrsIngester();
72 public: 72 public:
  73 + virtual void dispose();
  74 +public:
73 virtual int start(); 75 virtual int start();
74 virtual void stop(); 76 virtual void stop();
75 // interface ISrsReusableThreadHandler. 77 // interface ISrsReusableThreadHandler.
@@ -480,6 +480,7 @@ SrsServer::SrsServer() @@ -480,6 +480,7 @@ SrsServer::SrsServer()
480 { 480 {
481 signal_reload = false; 481 signal_reload = false;
482 signal_gmc_stop = false; 482 signal_gmc_stop = false;
  483 + signal_gracefully_quit = false;
483 pid_fd = -1; 484 pid_fd = -1;
484 485
485 signal_manager = NULL; 486 signal_manager = NULL;
@@ -519,7 +520,7 @@ void SrsServer::destroy() @@ -519,7 +520,7 @@ void SrsServer::destroy()
519 close_listeners(SrsListenerHttpStream); 520 close_listeners(SrsListenerHttpStream);
520 521
521 #ifdef SRS_AUTO_INGEST 522 #ifdef SRS_AUTO_INGEST
522 - ingester->stop(); 523 + ingester->dispose();
523 #endif 524 #endif
524 525
525 #ifdef SRS_AUTO_HTTP_API 526 #ifdef SRS_AUTO_HTTP_API
@@ -555,6 +556,18 @@ void SrsServer::destroy() @@ -555,6 +556,18 @@ void SrsServer::destroy()
555 // and segment fault. 556 // and segment fault.
556 } 557 }
557 558
  559 +void SrsServer::dispose()
  560 +{
  561 + _srs_config->unsubscribe(this);
  562 +
  563 +#ifdef SRS_AUTO_INGEST
  564 + ingester->dispose();
  565 + srs_trace("gracefully cleanup ingesters");
  566 +#endif
  567 +
  568 + srs_trace("terminate server");
  569 +}
  570 +
558 int SrsServer::initialize(ISrsServerCycle* cycle_handler) 571 int SrsServer::initialize(ISrsServerCycle* cycle_handler)
559 { 572 {
560 int ret = ERROR_SUCCESS; 573 int ret = ERROR_SUCCESS;
@@ -831,6 +844,7 @@ int SrsServer::cycle() @@ -831,6 +844,7 @@ int SrsServer::cycle()
831 srs_warn("system quit"); 844 srs_warn("system quit");
832 #else 845 #else
833 srs_warn("main cycle terminated, system quit normally."); 846 srs_warn("main cycle terminated, system quit normally.");
  847 + dispose();
834 exit(0); 848 exit(0);
835 #endif 849 #endif
836 850
@@ -877,9 +891,9 @@ void SrsServer::on_signal(int signo) @@ -877,9 +891,9 @@ void SrsServer::on_signal(int signo)
877 return; 891 return;
878 } 892 }
879 893
880 - if (signo == SIGTERM) {  
881 - srs_trace("user terminate program");  
882 - exit(0); 894 + if (signo == SIGTERM && !signal_gracefully_quit) {
  895 + srs_trace("user terminate program, gracefully quit.");
  896 + signal_gracefully_quit = true;
883 return; 897 return;
884 } 898 }
885 } 899 }
@@ -903,7 +917,7 @@ int SrsServer::do_cycle() @@ -903,7 +917,7 @@ int SrsServer::do_cycle()
903 917
904 // the deamon thread, update the time cache 918 // the deamon thread, update the time cache
905 while (true) { 919 while (true) {
906 - if(handler && (ret = handler->on_cycle(conns.size())) != ERROR_SUCCESS){ 920 + if(handler && (ret = handler->on_cycle((int)conns.size())) != ERROR_SUCCESS){
907 srs_error("cycle handle failed. ret=%d", ret); 921 srs_error("cycle handle failed. ret=%d", ret);
908 return ret; 922 return ret;
909 } 923 }
@@ -918,11 +932,17 @@ int SrsServer::do_cycle() @@ -918,11 +932,17 @@ int SrsServer::do_cycle()
918 for (int i = 0; i < temp_max; i++) { 932 for (int i = 0; i < temp_max; i++) {
919 st_usleep(SRS_SYS_CYCLE_INTERVAL * 1000); 933 st_usleep(SRS_SYS_CYCLE_INTERVAL * 1000);
920 934
921 -// for gperf heap checker,  
922 -// @see: research/gperftools/heap-checker/heap_checker.cc  
923 -// if user interrupt the program, exit to check mem leak.  
924 -// but, if gperf, use reload to ensure main return normally,  
925 -// because directly exit will cause core-dump. 935 + // gracefully quit for SIGINT or SIGTERM.
  936 + if (signal_gracefully_quit) {
  937 + srs_trace("cleanup for gracefully terminate.");
  938 + return ret;
  939 + }
  940 +
  941 + // for gperf heap checker,
  942 + // @see: research/gperftools/heap-checker/heap_checker.cc
  943 + // if user interrupt the program, exit to check mem leak.
  944 + // but, if gperf, use reload to ensure main return normally,
  945 + // because directly exit will cause core-dump.
926 #ifdef SRS_AUTO_GPERF_MC 946 #ifdef SRS_AUTO_GPERF_MC
927 if (signal_gmc_stop) { 947 if (signal_gmc_stop) {
928 srs_warn("gmc got singal to stop server."); 948 srs_warn("gmc got singal to stop server.");
@@ -930,6 +950,7 @@ int SrsServer::do_cycle() @@ -930,6 +950,7 @@ int SrsServer::do_cycle()
930 } 950 }
931 #endif 951 #endif
932 952
  953 + // do reload the config.
933 if (signal_reload) { 954 if (signal_reload) {
934 signal_reload = false; 955 signal_reload = false;
935 srs_info("get signal reload, to reload the config."); 956 srs_info("get signal reload, to reload the config.");
@@ -275,16 +275,22 @@ private: @@ -275,16 +275,22 @@ private:
275 */ 275 */
276 bool signal_reload; 276 bool signal_reload;
277 bool signal_gmc_stop; 277 bool signal_gmc_stop;
  278 + bool signal_gracefully_quit;
278 public: 279 public:
279 SrsServer(); 280 SrsServer();
280 virtual ~SrsServer(); 281 virtual ~SrsServer();
281 -public: 282 +private:
282 /** 283 /**
283 * the destroy is for gmc to analysis the memory leak, 284 * the destroy is for gmc to analysis the memory leak,
284 * if not destroy global/static data, the gmc will warning memory leak. 285 * if not destroy global/static data, the gmc will warning memory leak.
285 * in service, server never destroy, directly exit when restart. 286 * in service, server never destroy, directly exit when restart.
286 */ 287 */
287 virtual void destroy(); 288 virtual void destroy();
  289 + /**
  290 + * when SIGTERM, SRS should do cleanup, for example,
  291 + * to stop all ingesters, cleanup HLS and dvr.
  292 + */
  293 + virtual void dispose();
288 // server startup workflow, @see run_master() 294 // server startup workflow, @see run_master()
289 public: 295 public:
290 virtual int initialize(ISrsServerCycle* cycle_handler); 296 virtual int initialize(ISrsServerCycle* cycle_handler);