diff --git a/trunk/3rdparty/st-srs/Makefile b/trunk/3rdparty/st-srs/Makefile
index cc3fedf6d..14d4658bc 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 a81bee019..ed5a932fb 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 044c8221b..b6e8d232f 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 95683a3be..e91642a02 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 000000000..f3c7a88d6
--- /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 90d818ece..17033411c 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 56593602f..f7fdd3763 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 20fbec3d3..2cb9f9134 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 c62378295..53f721afd 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 707aa730d..399de60f0 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 db4a2ed45..cd32c2659 100644
--- a/trunk/src/app/srs_app_ingest.hpp
+++ b/trunk/src/app/srs_app_ingest.hpp
@@ -55,7 +55,7 @@ private:
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 472b7114b..21b50323c 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 3aa39d124..4ce4da410 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 3192f500c..419dd2bf0 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 ac4d68f7f..29249711b 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 2b1fa01c1..af9acf12d 100644
--- a/trunk/src/kernel/srs_kernel_error.hpp
+++ b/trunk/src/kernel/srs_kernel_error.hpp
@@ -468,7 +468,7 @@ public:
};
// 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 c101d1a9d..c34214759 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 375ab3d86..198b755b6 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);
}
}