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

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 <suzp1984@gmail.com>
This commit is contained in:
Winlin 2024-08-24 22:40:39 +08:00 committed by GitHub
parent cc6db250fb
commit f8319d6b6d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 89 additions and 161 deletions

View file

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

View file

@ -233,6 +233,17 @@ public:
};
#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:

View file

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

View file

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

View file

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

View file

@ -9,6 +9,6 @@
#define VERSION_MAJOR 6
#define VERSION_MINOR 0
#define VERSION_REVISION 150
#define VERSION_REVISION 151
#endif

View file

@ -9,6 +9,6 @@
#define VERSION_MAJOR 7
#define VERSION_MINOR 0
#define VERSION_REVISION 9
#define VERSION_REVISION 10
#endif

View file

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