diff --git a/trunk/etc/init.d/srs b/trunk/etc/init.d/srs index 9cfb7abda..3efcda350 100755 --- a/trunk/etc/init.d/srs +++ b/trunk/etc/init.d/srs @@ -109,12 +109,12 @@ stop() { ok_msg "Stopping SRS(pid ${srs_pid})..." # process exists, try to kill to stop normally - for((i=0;i<30;i++)); do + for((i=0;i<100;i++)); do load_process_info if [[ 0 -eq $? ]]; then kill -s SIGTERM ${srs_pid} 2>/dev/null ret=$?; if [[ 0 -ne $ret ]]; then failed_msg "send signal SIGTERM failed ret=$ret"; return $ret; fi - sleep 0.1 + sleep 0.3 else ok_msg "SRS stopped by SIGTERM" # delete the pid file when stop success. diff --git a/trunk/src/app/srs_app_ffmpeg.cpp b/trunk/src/app/srs_app_ffmpeg.cpp index 92dda2197..53b24f06f 100644 --- a/trunk/src/app/srs_app_ffmpeg.cpp +++ b/trunk/src/app/srs_app_ffmpeg.cpp @@ -52,6 +52,7 @@ using namespace std; SrsFFMPEG::SrsFFMPEG(std::string ffmpeg_bin) { started = false; + fast_stopped = false; pid = -1; ffmpeg = ffmpeg_bin; @@ -484,6 +485,11 @@ int SrsFFMPEG::cycle() return ret; } + // ffmpeg is prepare to stop, donot cycle. + if (fast_stopped) { + return ret; + } + int status = 0; pid_t p = waitpid(pid, &status, WNOHANG); @@ -524,6 +530,27 @@ void SrsFFMPEG::stop() started = false; } +void SrsFFMPEG::fast_stop() +{ + int ret = ERROR_SUCCESS; + + if (!started) { + return; + } + + if (pid <= 0) { + return; + } + + if (kill(pid, SIGTERM) < 0) { + ret = ERROR_SYSTEM_KILL; + srs_warn("ignore fast stop ffmpeg failed, pid=%d. ret=%d", pid, ret); + return; + } + + return; +} + #endif diff --git a/trunk/src/app/srs_app_ffmpeg.hpp b/trunk/src/app/srs_app_ffmpeg.hpp index 7c075c477..f96af8638 100644 --- a/trunk/src/app/srs_app_ffmpeg.hpp +++ b/trunk/src/app/srs_app_ffmpeg.hpp @@ -45,6 +45,8 @@ class SrsFFMPEG { private: bool started; + // whether SIGINT send but need to wait or SIGKILL. + bool fast_stopped; pid_t pid; private: std::string log_file; @@ -83,7 +85,25 @@ public: virtual int initialize_copy(); virtual int start(); virtual int cycle(); + /** + * send SIGTERM then SIGKILL to ensure the process stopped. + * the stop will wait [0, SRS_PROCESS_QUIT_TIMEOUT_MS] depends on the + * process quit timeout. + * @remark use fast_stop before stop one by one, when got lots of process to quit. + */ virtual void stop(); +public: + /** + * the fast stop is to send a SIGTERM. + * for example, the ingesters owner lots of FFMPEG, it will take a long time + * to stop one by one, instead the ingesters can fast_stop all FFMPEG, then + * wait one by one to stop, it's more faster. + * @remark user must use stop() to ensure the ffmpeg to stopped. + * @remark we got N processes to stop, compare the time we spend, + * when use stop without fast_stop, we spend maybe [0, SRS_PROCESS_QUIT_TIMEOUT_MS * N] + * but use fast_stop then stop, the time is almost [0, SRS_PROCESS_QUIT_TIMEOUT_MS]. + */ + virtual void fast_stop(); }; #endif diff --git a/trunk/src/app/srs_app_ingest.cpp b/trunk/src/app/srs_app_ingest.cpp index 986d5af23..2a5293e95 100644 --- a/trunk/src/app/srs_app_ingest.cpp +++ b/trunk/src/app/srs_app_ingest.cpp @@ -51,6 +51,11 @@ SrsIngesterFFMPEG::~SrsIngesterFFMPEG() srs_freep(ffmpeg); } +void SrsIngesterFFMPEG::fast_stop() +{ + ffmpeg->fast_stop(); +} + SrsIngester::SrsIngester() { _srs_config->subscribe(this); @@ -161,6 +166,18 @@ int SrsIngester::parse_engines(SrsConfDirective* vhost, SrsConfDirective* ingest void SrsIngester::dispose() { + // first, use fast stop to notice all FFMPEG to quit gracefully. + std::vector::iterator it; + for (it = ingesters.begin(); it != ingesters.end(); ++it) { + SrsIngesterFFMPEG* ingester = *it; + ingester->fast_stop(); + } + + if (!ingesters.empty()) { + srs_trace("fast stop all ingesters ok."); + } + + // then, use stop to wait FFMPEG quit one by one and send SIGKILL if needed. stop(); } diff --git a/trunk/src/app/srs_app_ingest.hpp b/trunk/src/app/srs_app_ingest.hpp index d10e1e414..ede1e5211 100644 --- a/trunk/src/app/srs_app_ingest.hpp +++ b/trunk/src/app/srs_app_ingest.hpp @@ -52,6 +52,9 @@ public: SrsIngesterFFMPEG(SrsFFMPEG* _ffmpeg, std::string _vhost, std::string _id); virtual ~SrsIngesterFFMPEG(); + + // @see SrsFFMPEG.fast_stop(). + virtual void fast_stop(); }; /** diff --git a/trunk/src/app/srs_app_utility.cpp b/trunk/src/app/srs_app_utility.cpp index ba64e8723..2f8b1248e 100644 --- a/trunk/src/app/srs_app_utility.cpp +++ b/trunk/src/app/srs_app_utility.cpp @@ -44,6 +44,9 @@ using namespace std; #include #include +// the longest time to wait for a process to quit. +#define SRS_PROCESS_QUIT_TIMEOUT_MS 1000 + int srs_socket_connect(string server, int port, int64_t timeout, st_netfd_t* pstfd) { int ret = ERROR_SUCCESS; @@ -223,7 +226,6 @@ void srs_parse_endpoint(string ip_port, string& ip, int& port) port = ::atoi(the_port.c_str()); } -#define SRS_PROCESS_QUIT_TIMEOUT_MS 1000 int srs_kill_forced(int& pid) { int ret = ERROR_SUCCESS; @@ -232,13 +234,13 @@ int srs_kill_forced(int& pid) return ret; } - // first, try kill by SIGINT. - if (kill(pid, SIGINT) < 0) { + // first, try kill by SIGTERM. + if (kill(pid, SIGTERM) < 0) { return ERROR_SYSTEM_KILL; } // wait to quit. - srs_trace("send SIGINT to pid=%d", pid); + srs_trace("send SIGTERM to pid=%d", pid); for (int i = 0; i < SRS_PROCESS_QUIT_TIMEOUT_MS / 10; i++) { int status = 0; pid_t qpid = -1; @@ -253,7 +255,7 @@ int srs_kill_forced(int& pid) } // killed, set pid to -1. - srs_trace("SIGINT stop process pid=%d ok.", pid); + srs_trace("SIGTERM stop process pid=%d ok.", pid); pid = -1; return ret;