From f8319d6b6d2eabb73240d24b8e941d3790f1c013 Mon Sep 17 00:00:00 2001 From: Winlin Date: Sat, 24 Aug 2024 22:40:39 +0800 Subject: [PATCH] Fix crash when quiting. v6.0.151 v7.0.10 (#4157) 1. Remove the srs_global_dispose, which causes the crash when still publishing when quit. 2. Always call _srs_thread_pool->initialize for single thread. 3. Support `--signal-api` to send signal by HTTP API, because CLion eliminate the signals. --- Co-authored-by: Jacob Su --- trunk/auto/auto_headers.sh | 5 + trunk/auto/options.sh | 4 + trunk/doc/CHANGELOG.md | 2 + trunk/src/app/srs_app_http_api.cpp | 54 +++++++++- trunk/src/app/srs_app_http_api.hpp | 11 ++ trunk/src/app/srs_app_server.cpp | 7 ++ trunk/src/app/srs_app_threads.cpp | 148 --------------------------- trunk/src/app/srs_app_threads.hpp | 1 - trunk/src/core/srs_core_version6.hpp | 2 +- trunk/src/core/srs_core_version7.hpp | 2 +- trunk/src/main/srs_main_server.cpp | 14 +-- 11 files changed, 89 insertions(+), 161 deletions(-) diff --git a/trunk/auto/auto_headers.sh b/trunk/auto/auto_headers.sh index 82d77186d5..34428955e0 100755 --- a/trunk/auto/auto_headers.sh +++ b/trunk/auto/auto_headers.sh @@ -201,6 +201,11 @@ if [[ $SRS_SINGLE_THREAD == YES ]]; then else srs_undefine_macro "SRS_SINGLE_THREAD" $SRS_AUTO_HEADERS_H fi +if [[ $SRS_SIGNAL_API == YES ]]; then + srs_define_macro "SRS_SIGNAL_API" $SRS_AUTO_HEADERS_H +else + srs_undefine_macro "SRS_SIGNAL_API" $SRS_AUTO_HEADERS_H +fi if [[ $SRS_LOG_LEVEL_V2 == YES ]]; then srs_define_macro "SRS_LOG_LEVEL_V2" $SRS_AUTO_HEADERS_H else diff --git a/trunk/auto/options.sh b/trunk/auto/options.sh index 9f43d6d075..03d58c54cd 100755 --- a/trunk/auto/options.sh +++ b/trunk/auto/options.sh @@ -85,6 +85,7 @@ SRS_CLEAN=YES # Whether do "make clean" when configure. SRS_SIMULATOR=NO # Whether enable RTC simulate API. SRS_GENERATE_OBJS=NO # Whether generate objs and quit. SRS_SINGLE_THREAD=YES # Whether force single thread mode. +SRS_SIGNAL_API=NO # Use http API to simulate sending signal to SRS, for debugging. # ################################################################ # Performance options. @@ -235,6 +236,7 @@ Experts: --simulator=on|off RTC: Whether enable network simulator. Default: $(value2switch $SRS_SIMULATOR) --generate-objs=on|off RTC: Whether generate objs and quit. Default: $(value2switch $SRS_GENERATE_OBJS) --single-thread=on|off Whether force single thread mode. Default: $(value2switch $SRS_SINGLE_THREAD) + --signal-api=on|off Whether support sending signal by HTTP API. Default: $(value2switch $SRS_SIGNAL_API) --build-tag= Set the build object directory suffix. --debug=on|off Whether enable the debug code, may hurt performance. Default: $(value2switch $SRS_DEBUG) --debug-stats=on|off Whether enable the debug stats, may hurt performance. Default: $(value2switch $SRS_DEBUG_STATS) @@ -339,6 +341,7 @@ function parse_user_option() { --simulator) SRS_SIMULATOR=$(switch2value $value) ;; --generate-objs) SRS_GENERATE_OBJS=$(switch2value $value) ;; --single-thread) SRS_SINGLE_THREAD=$(switch2value $value) ;; + --signal-api) SRS_SIGNAL_API=$(switch2value $value) ;; --ffmpeg-fit) SRS_FFMPEG_FIT=$(switch2value $value) ;; --ffmpeg-opus) SRS_FFMPEG_OPUS=$(switch2value $value) ;; --h265) SRS_H265=$(switch2value $value) ;; @@ -681,6 +684,7 @@ function regenerate_options() { SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --sanitizer-log=$(value2switch $SRS_SANITIZER_LOG)" SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --cygwin64=$(value2switch $SRS_CYGWIN64)" SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --single-thread=$(value2switch $SRS_SINGLE_THREAD)" + SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --signal-api=$(value2switch $SRS_SIGNAL_API)" SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --generic-linux=$(value2switch $SRS_GENERIC_LINUX)" SRS_AUTO_CONFIGURE="${SRS_AUTO_CONFIGURE} --build-cache=$(value2switch $SRS_BUILD_CACHE)" if [[ $SRS_CROSS_BUILD_ARCH != "" ]]; then SRS_AUTO_CONFIGURE="$SRS_AUTO_CONFIGURE --arch=$SRS_CROSS_BUILD_ARCH"; fi diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index 5b209dcd80..2ca58e9034 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -7,6 +7,7 @@ The changelog for SRS. ## SRS 7.0 Changelog +* v7.0, 2024-08-24, Merge [#4157](https://github.com/ossrs/srs/pull/4157): Fix crash when quiting. v7.0.10 (#4157) * v7.0, 2024-08-24, Merge [#4156](https://github.com/ossrs/srs/pull/4156): Build: Fix srs_mp4_parser compiling error. v7.0.9 (#4156) * v7.0, 2024-08-22, Merge [#4154](https://github.com/ossrs/srs/pull/4154): ASAN: Disable memory leak detection by default. v7.0.8 (#4154) * v7.0, 2024-08-21, Merge [#4149](https://github.com/ossrs/srs/pull/4149): ST: Replace macros with explicit code for better understanding. v7.0.7 (#4149) @@ -21,6 +22,7 @@ The changelog for SRS. ## SRS 6.0 Changelog +* v6.0, 2024-08-24, Merge [#4157](https://github.com/ossrs/srs/pull/4157): Fix crash when quiting. v6.0.151 (#4157) * v6.0, 2024-08-24, Merge [#4156](https://github.com/ossrs/srs/pull/4156): Build: Fix srs_mp4_parser compiling error. v6.0.150 (#4156) * v6.0, 2024-08-21, Merge [#4150](https://github.com/ossrs/srs/pull/4150): API: Support new HTTP API for VALGRIND. v6.0.149 (#4150) * v6.0, 2024-08-15, Merge [#4144](https://github.com/ossrs/srs/pull/4144): HTTP-FLV: Crash when multiple viewers. v6.0.148 (#4144) diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index b1bd339a43..a083a218a6 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -272,7 +272,12 @@ srs_error_t SrsGoApiV1::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r urls->set("clusters", SrsJsonAny::str("origin cluster server API")); urls->set("perf", SrsJsonAny::str("System performance stat")); urls->set("tcmalloc", SrsJsonAny::str("tcmalloc api with params ?page=summary|api")); +#ifdef SRS_VALGRIND urls->set("valgrind", SrsJsonAny::str("valgrind api with params ?check=full|added|changed|new|quick")); +#endif +#ifdef SRS_SIGNAL_API + urls->set("signal", SrsJsonAny::str("simulate signal api with params ?signo=SIGHUP|SIGUSR1|SIGUSR2|SIGTERM|SIGQUIT|SIGABRT|SIGINT")); +#endif SrsJsonObject* tests = SrsJsonAny::object(); obj->set("tests", tests); @@ -1097,7 +1102,6 @@ srs_error_t SrsGoApiTcmalloc::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMess #endif #ifdef SRS_VALGRIND - SrsGoApiValgrind::SrsGoApiValgrind() { trd_ = NULL; @@ -1191,6 +1195,54 @@ srs_error_t SrsGoApiValgrind::cycle() } #endif +#ifdef SRS_SIGNAL_API +SrsGoApiSignal::SrsGoApiSignal() +{ +} + +SrsGoApiSignal::~SrsGoApiSignal() +{ +} + +srs_error_t SrsGoApiSignal::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) +{ + srs_error_t err = srs_success; + + std::string signal = r->query_get("signo"); + srs_trace("query signo=%s", signal.c_str()); + + int signo = SIGINT; + if (signal == "SIGHUP") { + signo = SRS_SIGNAL_RELOAD; + } else if (signal == "SIGUSR1") { + signo = SRS_SIGNAL_REOPEN_LOG; + } else if (signal == "SIGUSR2") { + signo = SRS_SIGNAL_UPGRADE; + } else if (signal == "SIGTERM") { + signo = SRS_SIGNAL_FAST_QUIT; + } else if (signal == "SIGQUIT") { + signo = SRS_SIGNAL_GRACEFULLY_QUIT; + } else if (signal == "SIGABRT") { + signo = SRS_SIGNAL_ASSERT_ABORT; + } + + _srs_hybrid->srs()->instance()->on_signal(signo); + + // By default, response the json style response. + SrsUniquePtr obj(SrsJsonAny::object()); + + obj->set("code", SrsJsonAny::integer(ERROR_SUCCESS)); + + SrsJsonObject* res = SrsJsonAny::object(); + res->set("signal", SrsJsonAny::str(signal.c_str())); + res->set("help", SrsJsonAny::str("?signo=SIGHUP|SIGUSR1|SIGUSR2|SIGTERM|SIGQUIT|SIGABRT|SIGINT")); + res->set("signo", SrsJsonAny::integer(signo)); + obj->set("data", res); + + return srs_api_response(w, r, obj->dumps()); +} +#endif + SrsGoApiMetrics::SrsGoApiMetrics() { enabled_ = _srs_config->get_exporter_enabled(); diff --git a/trunk/src/app/srs_app_http_api.hpp b/trunk/src/app/srs_app_http_api.hpp index 8789d42e99..87428a0a5d 100644 --- a/trunk/src/app/srs_app_http_api.hpp +++ b/trunk/src/app/srs_app_http_api.hpp @@ -233,6 +233,17 @@ class SrsGoApiValgrind : public ISrsHttpHandler, public ISrsCoroutineHandler }; #endif +#ifdef SRS_SIGNAL_API +class SrsGoApiSignal : public ISrsHttpHandler +{ +public: + SrsGoApiSignal(); + virtual ~SrsGoApiSignal(); +public: + virtual srs_error_t serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r); +}; +#endif + class SrsGoApiMetrics : public ISrsHttpHandler { private: diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp index 16bc99e8c4..767429b242 100644 --- a/trunk/src/app/srs_app_server.cpp +++ b/trunk/src/app/srs_app_server.cpp @@ -784,6 +784,13 @@ srs_error_t SrsServer::http_handle() } #endif +#ifdef SRS_SIGNAL_API + // Simulate the signal by HTTP API, for debug signal issues in CLion. + if ((err = http_api_mux->handle("/api/v1/signal", new SrsGoApiSignal())) != srs_success) { + return srs_error_wrap(err, "handle signal errors"); + } +#endif + // metrics by prometheus if ((err = http_api_mux->handle("/metrics", new SrsGoApiMetrics())) != srs_success) { return srs_error_wrap(err, "handle tests errors"); diff --git a/trunk/src/app/srs_app_threads.cpp b/trunk/src/app/srs_app_threads.cpp index 4ce4da4109..3aa39d124d 100644 --- a/trunk/src/app/srs_app_threads.cpp +++ b/trunk/src/app/srs_app_threads.cpp @@ -455,154 +455,6 @@ srs_error_t srs_global_initialize() return err; } -void srs_global_dispose() -{ - // Note that hybrid depends on sources. - srs_freep(_srs_hybrid); - srs_freep(_srs_sources); - - srs_freep(_srs_clock); - - srs_freep(_srs_stages); - srs_freep(_srs_circuit_breaker); - -#ifdef SRS_SRT - srs_freep(_srs_srt_sources); -#endif - -#ifdef SRS_RTC - srs_freep(_srs_rtc_sources); - srs_freep(_srs_blackhole); - srs_freep(_srs_rtc_manager); - srs_freep(_srs_rtc_dtls_certificate); -#endif -#ifdef SRS_GB28181 - srs_freep(_srs_gb_manager); -#endif - - srs_freep(_srs_pps_ids); - srs_freep(_srs_pps_fids); - srs_freep(_srs_pps_fids_level0); - srs_freep(_srs_pps_dispose); - - srs_freep(_srs_pps_timer); - srs_freep(_srs_pps_conn); - srs_freep(_srs_pps_pub); - -#ifdef SRS_RTC - srs_freep(_srs_pps_snack); - srs_freep(_srs_pps_snack2); - srs_freep(_srs_pps_snack3); - srs_freep(_srs_pps_snack4); - srs_freep(_srs_pps_sanack); - srs_freep(_srs_pps_svnack); - - srs_freep(_srs_pps_rnack); - srs_freep(_srs_pps_rnack2); - srs_freep(_srs_pps_rhnack); - srs_freep(_srs_pps_rmnack); -#endif - -#if defined(SRS_DEBUG) && defined(SRS_DEBUG_STATS) - srs_freep(_srs_pps_recvfrom); - srs_freep(_srs_pps_recvfrom_eagain); - srs_freep(_srs_pps_sendto); - srs_freep(_srs_pps_sendto_eagain); - - srs_freep(_srs_pps_read); - srs_freep(_srs_pps_read_eagain); - srs_freep(_srs_pps_readv); - srs_freep(_srs_pps_readv_eagain); - srs_freep(_srs_pps_writev); - srs_freep(_srs_pps_writev_eagain); - - srs_freep(_srs_pps_recvmsg); - srs_freep(_srs_pps_recvmsg_eagain); - srs_freep(_srs_pps_sendmsg); - srs_freep(_srs_pps_sendmsg_eagain); - - srs_freep(_srs_pps_epoll); - srs_freep(_srs_pps_epoll_zero); - srs_freep(_srs_pps_epoll_shake); - srs_freep(_srs_pps_epoll_spin); - - srs_freep(_srs_pps_sched_15ms); - srs_freep(_srs_pps_sched_20ms); - srs_freep(_srs_pps_sched_25ms); - srs_freep(_srs_pps_sched_30ms); - srs_freep(_srs_pps_sched_35ms); - srs_freep(_srs_pps_sched_40ms); - srs_freep(_srs_pps_sched_80ms); - srs_freep(_srs_pps_sched_160ms); - srs_freep(_srs_pps_sched_s); -#endif - - srs_freep(_srs_pps_clock_15ms); - srs_freep(_srs_pps_clock_20ms); - srs_freep(_srs_pps_clock_25ms); - srs_freep(_srs_pps_clock_30ms); - srs_freep(_srs_pps_clock_35ms); - srs_freep(_srs_pps_clock_40ms); - srs_freep(_srs_pps_clock_80ms); - srs_freep(_srs_pps_clock_160ms); - srs_freep(_srs_pps_timer_s); - -#if defined(SRS_DEBUG) && defined(SRS_DEBUG_STATS) - srs_freep(_srs_pps_thread_run); - srs_freep(_srs_pps_thread_idle); - srs_freep(_srs_pps_thread_yield); - srs_freep(_srs_pps_thread_yield2); -#endif - - srs_freep(_srs_pps_rpkts); - srs_freep(_srs_pps_addrs); - srs_freep(_srs_pps_fast_addrs); - - srs_freep(_srs_pps_spkts); - srs_freep(_srs_pps_objs_msgs); - -#ifdef SRS_RTC - srs_freep(_srs_pps_sstuns); - srs_freep(_srs_pps_srtcps); - srs_freep(_srs_pps_srtps); - - srs_freep(_srs_pps_rstuns); - srs_freep(_srs_pps_rrtps); - srs_freep(_srs_pps_rrtcps); - - srs_freep(_srs_pps_aloss2); - - srs_freep(_srs_pps_pli); - srs_freep(_srs_pps_twcc); - srs_freep(_srs_pps_rr); - - srs_freep(_srs_pps_objs_rtps); - srs_freep(_srs_pps_objs_rraw); - srs_freep(_srs_pps_objs_rfua); - srs_freep(_srs_pps_objs_rbuf); - srs_freep(_srs_pps_objs_rothers); -#endif - - srs_freep(_srs_dvr_async); - -#ifdef SRS_APM - srs_freep(_srs_cls); - srs_freep(_srs_apm); -#endif - - srs_freep(_srs_reload_err); - - // Note that we never free the logging, because it's used after thread terminated. - //srs_freep(_srs_log); - //srs_freep(_srs_config); - //srs_freep(_srs_context); - //srs_freep(_srs_pps_cids_get); - //srs_freep(_srs_pps_cids_set); - - // Dispose ST finally, which may be used by other global objects. - srs_st_destroy(); -} - SrsThreadMutex::SrsThreadMutex() { // https://man7.org/linux/man-pages/man3/pthread_mutexattr_init.3.html diff --git a/trunk/src/app/srs_app_threads.hpp b/trunk/src/app/srs_app_threads.hpp index 419dd2bf0f..3192f500c4 100644 --- a/trunk/src/app/srs_app_threads.hpp +++ b/trunk/src/app/srs_app_threads.hpp @@ -53,7 +53,6 @@ extern SrsCircuitBreaker* _srs_circuit_breaker; // Initialize global shared variables cross all threads. extern srs_error_t srs_global_initialize(); -extern void srs_global_dispose(); // The thread mutex wrapper, without error. class SrsThreadMutex diff --git a/trunk/src/core/srs_core_version6.hpp b/trunk/src/core/srs_core_version6.hpp index 8f4585a2a1..edc5171e3c 100644 --- a/trunk/src/core/srs_core_version6.hpp +++ b/trunk/src/core/srs_core_version6.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 6 #define VERSION_MINOR 0 -#define VERSION_REVISION 150 +#define VERSION_REVISION 151 #endif diff --git a/trunk/src/core/srs_core_version7.hpp b/trunk/src/core/srs_core_version7.hpp index 1f3c2c3b2c..7cac790c41 100644 --- a/trunk/src/core/srs_core_version7.hpp +++ b/trunk/src/core/srs_core_version7.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 7 #define VERSION_MINOR 0 -#define VERSION_REVISION 9 +#define VERSION_REVISION 10 #endif \ No newline at end of file diff --git a/trunk/src/main/srs_main_server.cpp b/trunk/src/main/srs_main_server.cpp index 33aa7375f6..1a132d3f2b 100644 --- a/trunk/src/main/srs_main_server.cpp +++ b/trunk/src/main/srs_main_server.cpp @@ -463,17 +463,17 @@ srs_error_t run_directly_or_daemon() srs_error_t run_hybrid_server(void* arg); srs_error_t run_in_thread_pool() { -#ifdef SRS_SINGLE_THREAD - srs_trace("Run in single thread mode"); - return run_hybrid_server(NULL); -#else srs_error_t err = srs_success; - // Initialize the thread pool. + // Initialize the thread pool, even if we run in single thread mode. if ((err = _srs_thread_pool->initialize()) != srs_success) { return srs_error_wrap(err, "init thread pool"); } +#ifdef SRS_SINGLE_THREAD + srs_trace("Run in single thread mode"); + return run_hybrid_server(NULL); +#else // Start the hybrid service worker thread, for RTMP and RTC server, etc. if ((err = _srs_thread_pool->execute("hybrid", run_hybrid_server, (void*)NULL)) != srs_success) { return srs_error_wrap(err, "start hybrid server thread"); @@ -525,10 +525,6 @@ srs_error_t run_hybrid_server(void* /*arg*/) // After all done, stop and cleanup. _srs_hybrid->stop(); - // Dispose all global objects, note that we should do this in the hybrid thread, because it may - // depend on the ST when disposing. - srs_global_dispose(); - return err; }