From 7ab012c60f40934baf32e5c0fb5428b2feac543c Mon Sep 17 00:00:00 2001 From: Winlin Date: Sat, 29 Jun 2024 11:16:32 +0800 Subject: [PATCH] SmartPtr: Support detect memory leak by valgrind. v6.0.132 (#4102) 1. Support detect memory leak by valgrind. 2. Free the http handler entry. 3. Free the stack of ST. --- Co-authored-by: Jacob Su --- trunk/3rdparty/st-srs/Makefile | 3 + trunk/3rdparty/st-srs/stk.c | 31 +++- trunk/doc/CHANGELOG.md | 1 + trunk/research/st/.gitignore | 1 + trunk/research/st/thread-join.cpp | 36 +++++ trunk/src/app/srs_app_conn.cpp | 2 +- trunk/src/app/srs_app_hourglass.cpp | 2 +- trunk/src/app/srs_app_http_stream.cpp | 7 +- trunk/src/app/srs_app_hybrid.cpp | 86 +++++----- trunk/src/app/srs_app_ingest.cpp | 9 +- trunk/src/app/srs_app_ingest.hpp | 2 +- trunk/src/app/srs_app_server.cpp | 8 +- 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/kernel/srs_kernel_error.hpp | 2 +- trunk/src/main/srs_main_server.cpp | 7 + .../src/protocol/srs_protocol_http_stack.cpp | 7 +- 18 files changed, 286 insertions(+), 69 deletions(-) create mode 100644 trunk/research/st/thread-join.cpp diff --git a/trunk/3rdparty/st-srs/Makefile b/trunk/3rdparty/st-srs/Makefile index cc3fedf6de..14d4658bca 100644 --- a/trunk/3rdparty/st-srs/Makefile +++ b/trunk/3rdparty/st-srs/Makefile @@ -191,6 +191,9 @@ endif # # make EXTRA_CFLAGS=-DDEBUG_STATS # +# or cache the stack and reuse it: +# make EXTRA_CFLAGS=-DMD_CACHE_STACK +# # or enable the coverage for utest: # make UTEST_FLAGS="-fprofile-arcs -ftest-coverage" # diff --git a/trunk/3rdparty/st-srs/stk.c b/trunk/3rdparty/st-srs/stk.c index a81bee019b..ed5a932fbb 100644 --- a/trunk/3rdparty/st-srs/stk.c +++ b/trunk/3rdparty/st-srs/stk.c @@ -57,13 +57,15 @@ __thread int _st_num_free_stacks = 0; __thread int _st_randomize_stacks = 0; static char *_st_new_stk_segment(int size); +static void _st_delete_stk_segment(char *vaddr, int size); _st_stack_t *_st_stack_new(int stack_size) { _st_clist_t *qp; _st_stack_t *ts; int extra; - + +#ifdef MD_CACHE_STACK for (qp = _st_free_stacks.next; qp != &_st_free_stacks; qp = qp->next) { ts = _ST_THREAD_STACK_PTR(qp); if (ts->stk_size >= stack_size) { @@ -75,11 +77,31 @@ _st_stack_t *_st_stack_new(int stack_size) return ts; } } +#endif + + extra = _st_randomize_stacks ? _ST_PAGE_SIZE : 0; +#ifndef MD_CACHE_STACK + for (qp = _st_free_stacks.next; qp != &_st_free_stacks;) { + ts = _ST_THREAD_STACK_PTR(qp); + // Before qp is freed, move to next one, because the qp will be freed when free the ts. + qp = qp->next; + + ST_REMOVE_LINK(&ts->links); + _st_num_free_stacks--; + +#if defined(DEBUG) && !defined(MD_NO_PROTECT) + mprotect(ts->vaddr, REDZONE, PROT_READ | PROT_WRITE); + mprotect(ts->stk_top + extra, REDZONE, PROT_READ | PROT_WRITE); +#endif + + _st_delete_stk_segment(ts->vaddr, ts->vaddr_size); + free(ts); + } +#endif /* Make a new thread stack object. */ if ((ts = (_st_stack_t *)calloc(1, sizeof(_st_stack_t))) == NULL) return NULL; - extra = _st_randomize_stacks ? _ST_PAGE_SIZE : 0; ts->vaddr_size = stack_size + 2*REDZONE + extra; ts->vaddr = _st_new_stk_segment(ts->vaddr_size); if (!ts->vaddr) { @@ -114,7 +136,7 @@ void _st_stack_free(_st_stack_t *ts) { if (!ts) return; - + /* Put the stack on the free list */ ST_APPEND_LINK(&ts->links, _st_free_stacks.prev); _st_num_free_stacks++; @@ -152,8 +174,6 @@ static char *_st_new_stk_segment(int size) } -/* Not used */ -#if 0 void _st_delete_stk_segment(char *vaddr, int size) { #ifdef MALLOC_STACK @@ -162,7 +182,6 @@ void _st_delete_stk_segment(char *vaddr, int size) (void) munmap(vaddr, size); #endif } -#endif int st_randomize_stacks(int on) { diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index 044c8221b7..b6e8d232fa 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -7,6 +7,7 @@ The changelog for SRS. ## SRS 6.0 Changelog +* v6.0, 2024-06-29, Merge [#4102](https://github.com/ossrs/srs/pull/4102): SmartPtr: Support detect memory leak by valgrind. v6.0.132 (#4102) * v6.0, 2024-06-21, Merge [#4100](https://github.com/ossrs/srs/pull/4100): Fix security scan problems. v6.0.131 (#4100) * v6.0, 2024-06-21, Merge [#4097](https://github.com/ossrs/srs/pull/4097): SmartPtr: Support load test for source by srs-bench. v6.0.130 (#4097) * v6.0, 2024-06-15, Merge [#4089](https://github.com/ossrs/srs/pull/4089): SmartPtr: Support shared ptr for live source. v6.0.129 (#4089) diff --git a/trunk/research/st/.gitignore b/trunk/research/st/.gitignore index 95683a3be1..e91642a02a 100644 --- a/trunk/research/st/.gitignore +++ b/trunk/research/st/.gitignore @@ -2,3 +2,4 @@ udp-server udp-client cost cost.log +thread-join diff --git a/trunk/research/st/thread-join.cpp b/trunk/research/st/thread-join.cpp new file mode 100644 index 0000000000..f3c7a88d62 --- /dev/null +++ b/trunk/research/st/thread-join.cpp @@ -0,0 +1,36 @@ +/* +g++ thread-join.cpp ../../objs/st/libst.a -g -O0 -o thread-join && ./thread-join +*/ +#include +#include +#include "../../objs/st/st.h" + +void* pfn(void* arg) { + printf("pid=%d, coroutine is ok\n", ::getpid()); + return NULL; +} + +int main(int argc, char** argv) { + st_init(); + + printf("pid=%d, create coroutine #1\n", ::getpid()); + st_thread_t thread = st_thread_create(pfn, NULL, 1, 0); + st_thread_join(thread, NULL); + + st_usleep(100 * 1000); + + printf("pid=%d, create coroutine #2\n", ::getpid()); + thread = st_thread_create(pfn, NULL, 1, 0); + st_thread_join(thread, NULL); + + st_usleep(100 * 1000); + + printf("pid=%d, create coroutine #3\n", ::getpid()); + thread = st_thread_create(pfn, NULL, 1, 0); + st_thread_join(thread, NULL); + + printf("done\n"); + st_thread_exit(NULL); + return 0; +} + diff --git a/trunk/src/app/srs_app_conn.cpp b/trunk/src/app/srs_app_conn.cpp index 90d818ece0..17033411ce 100644 --- a/trunk/src/app/srs_app_conn.cpp +++ b/trunk/src/app/srs_app_conn.cpp @@ -54,8 +54,8 @@ SrsResourceManager::~SrsResourceManager() trd->stop(); srs_freep(trd); - srs_cond_destroy(cond); } + srs_cond_destroy(cond); clear(); diff --git a/trunk/src/app/srs_app_hourglass.cpp b/trunk/src/app/srs_app_hourglass.cpp index 56593602f6..f7fdd37634 100644 --- a/trunk/src/app/srs_app_hourglass.cpp +++ b/trunk/src/app/srs_app_hourglass.cpp @@ -166,7 +166,7 @@ void SrsFastTimer::unsubscribe(ISrsFastTimer* timer) { vector::iterator it = std::find(handlers_.begin(), handlers_.end(), timer); if (it != handlers_.end()) { - it = handlers_.erase(it); + handlers_.erase(it); } } diff --git a/trunk/src/app/srs_app_http_stream.cpp b/trunk/src/app/srs_app_http_stream.cpp index 20fbec3d37..2cb9f91343 100755 --- a/trunk/src/app/srs_app_http_stream.cpp +++ b/trunk/src/app/srs_app_http_stream.cpp @@ -1073,9 +1073,6 @@ void SrsHttpStreamServer::http_unmount(SrsRequest* r) SrsBufferCache* cache = entry->cache; SrsAutoFree(SrsBufferCache, cache); - // Unmount the HTTP handler. - mux.unhandle(entry->mount, stream); - // Notify cache and stream to stop. if (stream->entry) stream->entry->enabled = false; cache->stop(); @@ -1089,6 +1086,10 @@ void SrsHttpStreamServer::http_unmount(SrsRequest* r) srs_usleep(100 * SRS_UTIME_MILLISECONDS); } + // Unmount the HTTP handler, which will free the entry. Note that we must free it after cache and + // stream stopped for it uses it. + mux.unhandle(entry->mount, stream); + srs_trace("http: unmount flv stream for sid=%s, i=%d", sid.c_str(), i); } diff --git a/trunk/src/app/srs_app_hybrid.cpp b/trunk/src/app/srs_app_hybrid.cpp index c623782953..53f721afd0 100644 --- a/trunk/src/app/srs_app_hybrid.cpp +++ b/trunk/src/app/srs_app_hybrid.cpp @@ -25,21 +25,21 @@ extern SrsPps* _srs_pps_conn; extern SrsPps* _srs_pps_dispose; #if defined(SRS_DEBUG) && defined(SRS_DEBUG_STATS) -extern unsigned long long _st_stat_recvfrom; -extern unsigned long long _st_stat_recvfrom_eagain; -extern unsigned long long _st_stat_sendto; -extern unsigned long long _st_stat_sendto_eagain; +extern __thread unsigned long long _st_stat_recvfrom; +extern __thread unsigned long long _st_stat_recvfrom_eagain; +extern __thread unsigned long long _st_stat_sendto; +extern __thread unsigned long long _st_stat_sendto_eagain; SrsPps* _srs_pps_recvfrom = NULL; SrsPps* _srs_pps_recvfrom_eagain = NULL; SrsPps* _srs_pps_sendto = NULL; SrsPps* _srs_pps_sendto_eagain = NULL; -extern unsigned long long _st_stat_read; -extern unsigned long long _st_stat_read_eagain; -extern unsigned long long _st_stat_readv; -extern unsigned long long _st_stat_readv_eagain; -extern unsigned long long _st_stat_writev; -extern unsigned long long _st_stat_writev_eagain; +extern __thread unsigned long long _st_stat_read; +extern __thread unsigned long long _st_stat_read_eagain; +extern __thread unsigned long long _st_stat_readv; +extern __thread unsigned long long _st_stat_readv_eagain; +extern __thread unsigned long long _st_stat_writev; +extern __thread unsigned long long _st_stat_writev_eagain; SrsPps* _srs_pps_read = NULL; SrsPps* _srs_pps_read_eagain = NULL; SrsPps* _srs_pps_readv = NULL; @@ -47,33 +47,33 @@ SrsPps* _srs_pps_readv_eagain = NULL; SrsPps* _srs_pps_writev = NULL; SrsPps* _srs_pps_writev_eagain = NULL; -extern unsigned long long _st_stat_recvmsg; -extern unsigned long long _st_stat_recvmsg_eagain; -extern unsigned long long _st_stat_sendmsg; -extern unsigned long long _st_stat_sendmsg_eagain; +extern __thread unsigned long long _st_stat_recvmsg; +extern __thread unsigned long long _st_stat_recvmsg_eagain; +extern __thread unsigned long long _st_stat_sendmsg; +extern __thread unsigned long long _st_stat_sendmsg_eagain; SrsPps* _srs_pps_recvmsg = NULL; SrsPps* _srs_pps_recvmsg_eagain = NULL; SrsPps* _srs_pps_sendmsg = NULL; SrsPps* _srs_pps_sendmsg_eagain = NULL; -extern unsigned long long _st_stat_epoll; -extern unsigned long long _st_stat_epoll_zero; -extern unsigned long long _st_stat_epoll_shake; -extern unsigned long long _st_stat_epoll_spin; +extern __thread unsigned long long _st_stat_epoll; +extern __thread unsigned long long _st_stat_epoll_zero; +extern __thread unsigned long long _st_stat_epoll_shake; +extern __thread unsigned long long _st_stat_epoll_spin; SrsPps* _srs_pps_epoll = NULL; SrsPps* _srs_pps_epoll_zero = NULL; SrsPps* _srs_pps_epoll_shake = NULL; SrsPps* _srs_pps_epoll_spin = NULL; -extern unsigned long long _st_stat_sched_15ms; -extern unsigned long long _st_stat_sched_20ms; -extern unsigned long long _st_stat_sched_25ms; -extern unsigned long long _st_stat_sched_30ms; -extern unsigned long long _st_stat_sched_35ms; -extern unsigned long long _st_stat_sched_40ms; -extern unsigned long long _st_stat_sched_80ms; -extern unsigned long long _st_stat_sched_160ms; -extern unsigned long long _st_stat_sched_s; +extern __thread unsigned long long _st_stat_sched_15ms; +extern __thread unsigned long long _st_stat_sched_20ms; +extern __thread unsigned long long _st_stat_sched_25ms; +extern __thread unsigned long long _st_stat_sched_30ms; +extern __thread unsigned long long _st_stat_sched_35ms; +extern __thread unsigned long long _st_stat_sched_40ms; +extern __thread unsigned long long _st_stat_sched_80ms; +extern __thread unsigned long long _st_stat_sched_160ms; +extern __thread unsigned long long _st_stat_sched_s; SrsPps* _srs_pps_sched_15ms = NULL; SrsPps* _srs_pps_sched_20ms = NULL; SrsPps* _srs_pps_sched_25ms = NULL; @@ -96,11 +96,12 @@ SrsPps* _srs_pps_clock_160ms = NULL; SrsPps* _srs_pps_timer_s = NULL; #if defined(SRS_DEBUG) && defined(SRS_DEBUG_STATS) -extern int _st_active_count; -extern unsigned long long _st_stat_thread_run; -extern unsigned long long _st_stat_thread_idle; -extern unsigned long long _st_stat_thread_yield; -extern unsigned long long _st_stat_thread_yield2; +extern __thread int _st_active_count; +extern __thread int _st_num_free_stacks; +extern __thread unsigned long long _st_stat_thread_run; +extern __thread unsigned long long _st_stat_thread_idle; +extern __thread unsigned long long _st_stat_thread_yield; +extern __thread unsigned long long _st_stat_thread_yield2; SrsPps* _srs_pps_thread_run = NULL; SrsPps* _srs_pps_thread_idle = NULL; SrsPps* _srs_pps_thread_yield = NULL; @@ -135,19 +136,20 @@ SrsHybridServer::SrsHybridServer() SrsHybridServer::~SrsHybridServer() { - srs_freep(clock_monitor_); - - srs_freep(timer20ms_); - srs_freep(timer100ms_); - srs_freep(timer1s_); - srs_freep(timer5s_); - + // We must free servers first, because it may depend on the timers of hybrid server. vector::iterator it; for (it = servers.begin(); it != servers.end(); ++it) { ISrsHybridServer* server = *it; srs_freep(server); } servers.clear(); + + srs_freep(clock_monitor_); + + srs_freep(timer20ms_); + srs_freep(timer100ms_); + srs_freep(timer1s_); + srs_freep(timer5s_); } void SrsHybridServer::register_server(ISrsHybridServer* svr) @@ -237,8 +239,6 @@ void SrsHybridServer::stop() ISrsHybridServer* server = *it; server->stop(); } - - srs_st_destroy(); } SrsServerAdapter* SrsHybridServer::srs() @@ -372,8 +372,8 @@ srs_error_t SrsHybridServer::on_timer(srs_utime_t interval) #if defined(SRS_DEBUG) && defined(SRS_DEBUG_STATS) _srs_pps_thread_run->update(_st_stat_thread_run); _srs_pps_thread_idle->update(_st_stat_thread_idle); _srs_pps_thread_yield->update(_st_stat_thread_yield); _srs_pps_thread_yield2->update(_st_stat_thread_yield2); - if (_st_active_count > 0 || _srs_pps_thread_run->r10s() || _srs_pps_thread_idle->r10s() || _srs_pps_thread_yield->r10s() || _srs_pps_thread_yield2->r10s()) { - snprintf(buf, sizeof(buf), ", co=%d,%d,%d, yield=%d,%d", _st_active_count, _srs_pps_thread_run->r10s(), _srs_pps_thread_idle->r10s(), _srs_pps_thread_yield->r10s(), _srs_pps_thread_yield2->r10s()); + if (_st_active_count > 0 || _st_num_free_stacks > 0 || _srs_pps_thread_run->r10s() || _srs_pps_thread_idle->r10s() || _srs_pps_thread_yield->r10s() || _srs_pps_thread_yield2->r10s()) { + snprintf(buf, sizeof(buf), ", co=%d,%d,%d, stk=%d, yield=%d,%d", _st_active_count, _srs_pps_thread_run->r10s(), _srs_pps_thread_idle->r10s(), _st_num_free_stacks, _srs_pps_thread_yield->r10s(), _srs_pps_thread_yield2->r10s()); thread_desc = buf; } #endif diff --git a/trunk/src/app/srs_app_ingest.cpp b/trunk/src/app/srs_app_ingest.cpp index 707aa730d1..399de60f02 100644 --- a/trunk/src/app/srs_app_ingest.cpp +++ b/trunk/src/app/srs_app_ingest.cpp @@ -94,7 +94,7 @@ SrsIngester::SrsIngester() disposed = false; trd = new SrsDummyCoroutine(); - pprint = SrsPithyPrint::create_ingester(); + pprint_ = SrsPithyPrint::create_ingester(); } SrsIngester::~SrsIngester() @@ -103,6 +103,7 @@ SrsIngester::~SrsIngester() srs_freep(trd); clear_engines(); + srs_freep(pprint_); } void SrsIngester::dispose() @@ -466,7 +467,7 @@ srs_error_t SrsIngester::initialize_ffmpeg(SrsFFMPEG* ffmpeg, SrsConfDirective* void SrsIngester::show_ingest_log_message() { - pprint->elapse(); + pprint_->elapse(); if ((int)ingesters.size() <= 0) { return; @@ -477,9 +478,9 @@ void SrsIngester::show_ingest_log_message() SrsIngesterFFMPEG* ingester = ingesters.at(index); // reportable - if (pprint->can_print()) { + if (pprint_->can_print()) { srs_trace("-> " SRS_CONSTS_LOG_INGESTER " time=%dms, ingesters=%d, #%d(alive=%dms, %s)", - srsu2msi(pprint->age()), (int)ingesters.size(), index, srsu2msi(ingester->alive()), ingester->uri().c_str()); + srsu2msi(pprint_->age()), (int)ingesters.size(), index, srsu2msi(ingester->alive()), ingester->uri().c_str()); } } diff --git a/trunk/src/app/srs_app_ingest.hpp b/trunk/src/app/srs_app_ingest.hpp index db4a2ed45c..cd32c2659a 100644 --- a/trunk/src/app/srs_app_ingest.hpp +++ b/trunk/src/app/srs_app_ingest.hpp @@ -55,7 +55,7 @@ class SrsIngester : public ISrsCoroutineHandler, public ISrsReloadHandler std::vector ingesters; private: SrsCoroutine* trd; - SrsPithyPrint* pprint; + SrsPithyPrint* pprint_; // Whether the ingesters are expired, for example, the listen port changed, // all ingesters must be restart. bool expired; diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp index 472b7114b3..21b50323cd 100644 --- a/trunk/src/app/srs_app_server.cpp +++ b/trunk/src/app/srs_app_server.cpp @@ -370,8 +370,6 @@ SrsServer::~SrsServer() void SrsServer::destroy() { - srs_warn("start destroy server"); - srs_freep(trd_); srs_freep(timer_); @@ -869,11 +867,8 @@ void SrsServer::stop() srs_trace("srs gracefully quit"); } + // This is the last line log of SRS. srs_trace("srs terminated"); - - // for valgrind to detect. - srs_freep(_srs_config); - srs_freep(_srs_log); } srs_error_t SrsServer::cycle() @@ -1406,6 +1401,7 @@ srs_error_t SrsServerAdapter::run(SrsWaitGroup* wg) void SrsServerAdapter::stop() { + srs->stop(); } SrsServer* SrsServerAdapter::instance() diff --git a/trunk/src/app/srs_app_threads.cpp b/trunk/src/app/srs_app_threads.cpp index 3aa39d124d..4ce4da4109 100644 --- a/trunk/src/app/srs_app_threads.cpp +++ b/trunk/src/app/srs_app_threads.cpp @@ -455,6 +455,154 @@ 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 3192f500c4..419dd2bf0f 100644 --- a/trunk/src/app/srs_app_threads.hpp +++ b/trunk/src/app/srs_app_threads.hpp @@ -53,6 +53,7 @@ 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 ac4d68f7fa..29249711b6 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 131 +#define VERSION_REVISION 132 #endif diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index 2b1fa01c1d..af9acf12de 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -468,7 +468,7 @@ class SrsCplxError }; // Error helpers, should use these functions to new or wrap an error. -#define srs_success 0 // SrsCplxError::success() +#define srs_success NULL // SrsCplxError::success() #define srs_error_new(ret, fmt, ...) SrsCplxError::create(__FUNCTION__, __FILE__, __LINE__, ret, fmt, ##__VA_ARGS__) #define srs_error_wrap(err, fmt, ...) SrsCplxError::wrap(__FUNCTION__, __FILE__, __LINE__, err, fmt, ##__VA_ARGS__) #define srs_error_copy(err) SrsCplxError::copy(err) diff --git a/trunk/src/main/srs_main_server.cpp b/trunk/src/main/srs_main_server.cpp index c101d1a9df..c34214759d 100644 --- a/trunk/src/main/srs_main_server.cpp +++ b/trunk/src/main/srs_main_server.cpp @@ -88,6 +88,9 @@ extern void srs_free_global_system_ips(); extern void asan_report_callback(const char* str); #endif +extern SrsPps* _srs_pps_cids_get; +extern SrsPps* _srs_pps_cids_set; + /** * main entrance. */ @@ -522,6 +525,10 @@ 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; } diff --git a/trunk/src/protocol/srs_protocol_http_stack.cpp b/trunk/src/protocol/srs_protocol_http_stack.cpp index 375ab3d860..198b755b68 100644 --- a/trunk/src/protocol/srs_protocol_http_stack.cpp +++ b/trunk/src/protocol/srs_protocol_http_stack.cpp @@ -761,9 +761,12 @@ void SrsHttpServeMux::unhandle(std::string pattern, ISrsHttpHandler* handler) entries.erase(it); // We don't free the handler, because user should free it. - if (entry->handler != handler) { - srs_freep(entry); + if (entry->handler == handler) { + entry->handler = NULL; } + + // Should always free the entry. + srs_freep(entry); } }