winlin

for #374, use SIGINT then SIGKILL to try to kill FFMPEG gracefullly.

@@ -35,6 +35,7 @@ using namespace std; @@ -35,6 +35,7 @@ using namespace std;
35 #include <srs_kernel_error.hpp> 35 #include <srs_kernel_error.hpp>
36 #include <srs_kernel_log.hpp> 36 #include <srs_kernel_log.hpp>
37 #include <srs_app_config.hpp> 37 #include <srs_app_config.hpp>
  38 +#include <srs_app_utility.hpp>
38 39
39 #ifdef SRS_AUTO_FFMPEG_STUB 40 #ifdef SRS_AUTO_FFMPEG_STUB
40 41
@@ -509,24 +510,14 @@ void SrsFFMPEG::stop() @@ -509,24 +510,14 @@ void SrsFFMPEG::stop()
509 // when rewind, upstream will stop publish(unpublish), 510 // when rewind, upstream will stop publish(unpublish),
510 // unpublish event will stop all ffmpeg encoders, 511 // unpublish event will stop all ffmpeg encoders,
511 // then publish will start all ffmpeg encoders. 512 // then publish will start all ffmpeg encoders.
512 - if (pid > 0) {  
513 - if (kill(pid, SIGKILL) < 0) {  
514 - srs_warn("kill the encoder failed, ignored. pid=%d", pid);  
515 - }  
516 -  
517 - // wait for the ffmpeg to quit.  
518 - // ffmpeg will gracefully quit if signal is:  
519 - // 1) SIGHUP 2) SIGINT 3) SIGQUIT  
520 - // other signals, directly exit(123), for example:  
521 - // 9) SIGKILL 15) SIGTERM  
522 - int status = 0;  
523 - if (waitpid(pid, &status, 0) < 0) {  
524 - srs_warn("wait the encoder quit failed, ignored. pid=%d", pid);  
525 - }  
526 -  
527 - srs_trace("stop the encoder success. pid=%d", pid);  
528 - pid = -1; 513 + int ret = srs_kill_forced(pid);
  514 + if (ret != ERROR_SUCCESS) {
  515 + srs_warn("ignore kill the encoder failed, pid=%d. ret=%d", pid, ret);
  516 + return;
529 } 517 }
  518 +
  519 + // terminated, set started to false to stop the cycle.
  520 + started = false;
530 } 521 }
531 522
532 #endif 523 #endif
@@ -27,6 +27,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -27,6 +27,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 #include <unistd.h> 27 #include <unistd.h>
28 #include <ifaddrs.h> 28 #include <ifaddrs.h>
29 #include <arpa/inet.h> 29 #include <arpa/inet.h>
  30 +#include <signal.h>
30 31
31 #ifdef SRS_OSX 32 #ifdef SRS_OSX
32 #include <sys/sysctl.h> 33 #include <sys/sysctl.h>
@@ -222,6 +223,63 @@ void srs_parse_endpoint(string ip_port, string& ip, int& port) @@ -222,6 +223,63 @@ void srs_parse_endpoint(string ip_port, string& ip, int& port)
222 port = ::atoi(the_port.c_str()); 223 port = ::atoi(the_port.c_str());
223 } 224 }
224 225
  226 +#define SRS_PROCESS_QUIT_TIMEOUT_MS 1000
  227 +int srs_kill_forced(int& pid)
  228 +{
  229 + int ret = ERROR_SUCCESS;
  230 +
  231 + if (pid <= 0) {
  232 + return ret;
  233 + }
  234 +
  235 + // first, try kill by SIGINT.
  236 + if (kill(pid, SIGINT) < 0) {
  237 + return ERROR_SYSTEM_KILL;
  238 + }
  239 +
  240 + // wait to quit.
  241 + srs_trace("send SIGINT to pid=%d", pid);
  242 + for (int i = 0; i < SRS_PROCESS_QUIT_TIMEOUT_MS / 10; i++) {
  243 + int status = 0;
  244 + pid_t qpid = -1;
  245 + if ((qpid = waitpid(pid, &status, WNOHANG)) < 0) {
  246 + return ERROR_SYSTEM_KILL;
  247 + }
  248 +
  249 + // 0 is not quit yet.
  250 + if (qpid == 0) {
  251 + st_usleep(10 * 1000);
  252 + continue;
  253 + }
  254 +
  255 + // killed, set pid to -1.
  256 + srs_trace("SIGINT stop process pid=%d ok.", pid);
  257 + pid = -1;
  258 +
  259 + return ret;
  260 + }
  261 +
  262 + // then, try kill by SIGKILL.
  263 + if (kill(pid, SIGKILL) < 0) {
  264 + return ERROR_SYSTEM_KILL;
  265 + }
  266 +
  267 + // wait for the process to quit.
  268 + // for example, ffmpeg will gracefully quit if signal is:
  269 + // 1) SIGHUP 2) SIGINT 3) SIGQUIT
  270 + // other signals, directly exit(123), for example:
  271 + // 9) SIGKILL 15) SIGTERM
  272 + int status = 0;
  273 + if (waitpid(pid, &status, 0) < 0) {
  274 + return ERROR_SYSTEM_KILL;
  275 + }
  276 +
  277 + srs_trace("SIGKILL stop process pid=%d ok.", pid);
  278 + pid = -1;
  279 +
  280 + return ret;
  281 +}
  282 +
225 static SrsRusage _srs_system_rusage; 283 static SrsRusage _srs_system_rusage;
226 284
227 SrsRusage::SrsRusage() 285 SrsRusage::SrsRusage()
@@ -422,7 +480,7 @@ void srs_update_proc_stat() @@ -422,7 +480,7 @@ void srs_update_proc_stat()
422 // @see https://github.com/simple-rtmp-server/srs/issues/397 480 // @see https://github.com/simple-rtmp-server/srs/issues/397
423 static int user_hz = 0; 481 static int user_hz = 0;
424 if (user_hz <= 0) { 482 if (user_hz <= 0) {
425 - user_hz = sysconf(_SC_CLK_TCK); 483 + user_hz = (int)sysconf(_SC_CLK_TCK);
426 srs_trace("USER_HZ=%d", user_hz); 484 srs_trace("USER_HZ=%d", user_hz);
427 srs_assert(user_hz > 0); 485 srs_assert(user_hz > 0);
428 } 486 }
@@ -646,12 +704,12 @@ void srs_update_disk_stat() @@ -646,12 +704,12 @@ void srs_update_disk_stat()
646 704
647 if (o.pgpgin > 0 && r.pgpgin > o.pgpgin && duration_ms > 0) { 705 if (o.pgpgin > 0 && r.pgpgin > o.pgpgin && duration_ms > 0) {
648 // KBps = KB * 1000 / ms = KB/s 706 // KBps = KB * 1000 / ms = KB/s
649 - r.in_KBps = (r.pgpgin - o.pgpgin) * 1000 / duration_ms; 707 + r.in_KBps = (int)((r.pgpgin - o.pgpgin) * 1000 / duration_ms);
650 } 708 }
651 709
652 if (o.pgpgout > 0 && r.pgpgout > o.pgpgout && duration_ms > 0) { 710 if (o.pgpgout > 0 && r.pgpgout > o.pgpgout && duration_ms > 0) {
653 // KBps = KB * 1000 / ms = KB/s 711 // KBps = KB * 1000 / ms = KB/s
654 - r.out_KBps = (r.pgpgout - o.pgpgout) * 1000 / duration_ms; 712 + r.out_KBps = (int)((r.pgpgout - o.pgpgout) * 1000 / duration_ms);
655 } 713 }
656 } 714 }
657 715
@@ -771,8 +829,8 @@ SrsCpuInfo* srs_get_cpuinfo() @@ -771,8 +829,8 @@ SrsCpuInfo* srs_get_cpuinfo()
771 // initialize cpu info. 829 // initialize cpu info.
772 cpu = new SrsCpuInfo(); 830 cpu = new SrsCpuInfo();
773 cpu->ok = true; 831 cpu->ok = true;
774 - cpu->nb_processors = sysconf(_SC_NPROCESSORS_CONF);  
775 - cpu->nb_processors_online = sysconf(_SC_NPROCESSORS_ONLN); 832 + cpu->nb_processors = (int)sysconf(_SC_NPROCESSORS_CONF);
  833 + cpu->nb_processors_online = (int)sysconf(_SC_NPROCESSORS_ONLN);
776 834
777 return cpu; 835 return cpu;
778 } 836 }
@@ -80,6 +80,14 @@ extern std::string srs_path_build_timestamp(std::string template_path); @@ -80,6 +80,14 @@ extern std::string srs_path_build_timestamp(std::string template_path);
80 extern void srs_parse_endpoint(std::string ip_port, std::string& ip, std::string& port); 80 extern void srs_parse_endpoint(std::string ip_port, std::string& ip, std::string& port);
81 extern void srs_parse_endpoint(std::string ip_port, std::string& ip, int& port); 81 extern void srs_parse_endpoint(std::string ip_port, std::string& ip, int& port);
82 82
  83 +/**
  84 + * kill the pid by SIGINT, then wait to quit,
  85 + * kill the pid by SIGKILL again when exceed the timeout.
  86 + * @param pid the pid to kill. ignore for -1. set to -1 when killed.
  87 + * @return an int error code.
  88 + */
  89 +extern int srs_kill_forced(int& pid);
  90 +
83 // current process resouce usage. 91 // current process resouce usage.
84 // @see: man getrusage 92 // @see: man getrusage
85 class SrsRusage 93 class SrsRusage
@@ -96,6 +96,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -96,6 +96,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
96 #define ERROR_SYSTEM_TIME 1055 96 #define ERROR_SYSTEM_TIME 1055
97 #define ERROR_SYSTEM_DIR_EXISTS 1056 97 #define ERROR_SYSTEM_DIR_EXISTS 1056
98 #define ERROR_SYSTEM_CREATE_DIR 1057 98 #define ERROR_SYSTEM_CREATE_DIR 1057
  99 +#define ERROR_SYSTEM_KILL 1058
99 100
100 /////////////////////////////////////////////////////// 101 ///////////////////////////////////////////////////////
101 // RTMP protocol error. 102 // RTMP protocol error.