1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

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 <suzp1984@gmail.com>
This commit is contained in:
Winlin 2024-06-29 11:16:32 +08:00 committed by GitHub
parent ea7e2c2849
commit 7ab012c60f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 286 additions and 69 deletions

View file

@ -54,8 +54,8 @@ SrsResourceManager::~SrsResourceManager()
trd->stop();
srs_freep(trd);
srs_cond_destroy(cond);
}
srs_cond_destroy(cond);
clear();

View file

@ -166,7 +166,7 @@ void SrsFastTimer::unsubscribe(ISrsFastTimer* timer)
{
vector<ISrsFastTimer*>::iterator it = std::find(handlers_.begin(), handlers_.end(), timer);
if (it != handlers_.end()) {
it = handlers_.erase(it);
handlers_.erase(it);
}
}

View file

@ -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);
}

View file

@ -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<ISrsHybridServer*>::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

View file

@ -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());
}
}

View file

@ -55,7 +55,7 @@ private:
std::vector<SrsIngesterFFMPEG*> 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;

View file

@ -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()

View file

@ -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

View file

@ -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

View file

@ -9,6 +9,6 @@
#define VERSION_MAJOR 6
#define VERSION_MINOR 0
#define VERSION_REVISION 131
#define VERSION_REVISION 132
#endif

View file

@ -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)

View file

@ -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;
}

View file

@ -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);
}
}