From 69cae4f46c8b25fbe2e5802741c9f8bf38413c7f Mon Sep 17 00:00:00 2001 From: Zhengwei Zhu Date: Thu, 23 Oct 2025 16:47:07 +0800 Subject: [PATCH] feat: make bthread stack trace signal number configurable --- src/bthread/task_control.cpp | 3 +-- src/bthread/task_tracer.cpp | 12 +++++++++--- src/bthread/task_tracer.h | 6 +++++- test/brpc_builtin_service_unittest.cpp | 10 ++++++++++ 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/bthread/task_control.cpp b/src/bthread/task_control.cpp index feeeb7d459..21a505c791 100644 --- a/src/bthread/task_control.cpp +++ b/src/bthread/task_control.cpp @@ -343,8 +343,7 @@ void TaskControl::stop_and_join() { for (auto worker: _workers) { // Interrupt blocking operations. #ifdef BRPC_BTHREAD_TRACER - // TaskTracer has registered signal handler for SIGURG. - pthread_kill(worker, SIGURG); + pthread_kill(worker, _task_tracer.get_trace_signal()); #else interrupt_pthread(worker); #endif // BRPC_BTHREAD_TRACER diff --git a/src/bthread/task_tracer.cpp b/src/bthread/task_tracer.cpp index f9d14f02c2..ef63d14bd3 100644 --- a/src/bthread/task_tracer.cpp +++ b/src/bthread/task_tracer.cpp @@ -35,6 +35,10 @@ namespace bthread { DEFINE_uint32(signal_trace_timeout_ms, 50, "Timeout for signal trace in ms"); BUTIL_VALIDATE_GFLAG(signal_trace_timeout_ms, butil::PositiveInteger); +// Note that SIGURG handler may be registered by some library such as cgo +// so let the signal number be configurable +DEFINE_int32(signal_number_for_trace, SIGURG, + "signal number used for stack trace, default to SIGURG"); extern BAIDU_THREAD_LOCAL TaskMeta* pthread_fake_meta; @@ -315,17 +319,19 @@ TaskTracer::Result TaskTracer::TraceByLibunwind(unw_cursor_t& cursor) { bool TaskTracer::RegisterSignalHandler() { // Set up the signal handler. + _signal_num = FLAGS_signal_number_for_trace; struct sigaction old_sa{}; struct sigaction sa{}; sa.sa_sigaction = SignalHandler; sa.sa_flags = SA_SIGINFO; sigfillset(&sa.sa_mask); - if (sigaction(SIGURG, &sa, &old_sa) != 0) { + if (sigaction(_signal_num, &sa, &old_sa) != 0) { PLOG(ERROR) << "Failed to sigaction"; return false; } if (NULL != old_sa.sa_handler || NULL != old_sa.sa_sigaction) { - LOG(ERROR) << "Signal handler of SIGURG is already registered"; + LOG(ERROR) << "Signal handler of signal number " + << _signal_num << " is already registered"; return false; } @@ -403,7 +409,7 @@ TaskTracer::Result TaskTracer::SignalTrace(pthread_t worker_tid) { sigval value{}; value.sival_ptr = signal_sync.get(); size_t sigqueue_try = 0; - while (pthread_sigqueue(worker_tid, SIGURG, value) != 0) { + while (pthread_sigqueue(worker_tid, _signal_num, value) != 0) { if (errno != EAGAIN || sigqueue_try++ >= 3) { // Remove reference for SignalHandler. signal_sync->RemoveRefManually(); diff --git a/src/bthread/task_tracer.h b/src/bthread/task_tracer.h index be95f3ac80..8844413af6 100644 --- a/src/bthread/task_tracer.h +++ b/src/bthread/task_tracer.h @@ -49,6 +49,9 @@ class TaskTracer { // When the worker is jumping stack from a bthread to another, static void WaitForTracing(TaskMeta* m); + int get_trace_signal() const { + return _signal_num; + } private: // Error number guard used in signal handler. class ErrnoGuard { @@ -100,7 +103,7 @@ class TaskTracer { Result ContextTrace(bthread_fcontext_t fcontext); static Result TraceByLibunwind(unw_cursor_t& cursor); - static bool RegisterSignalHandler(); + bool RegisterSignalHandler(); static void SignalHandler(int sig, siginfo_t* info, void* context); Result SignalTrace(pthread_t worker_tid); @@ -115,6 +118,7 @@ class TaskTracer { std::vector> _inuse_signal_syncs; bvar::LatencyRecorder _trace_time{"bthread_trace_time"}; + int _signal_num{SIGURG}; }; } // namespace bthread diff --git a/test/brpc_builtin_service_unittest.cpp b/test/brpc_builtin_service_unittest.cpp index 4ba8a0398e..da4d6f1026 100644 --- a/test/brpc_builtin_service_unittest.cpp +++ b/test/brpc_builtin_service_unittest.cpp @@ -66,9 +66,19 @@ DECLARE_bool(rpcz_hex_log_id); DECLARE_int32(idle_timeout_second); } // namespace rpc +#ifdef BRPC_BTHREAD_TRACER +namespace bthread { +DECLARE_int32(signal_number_for_trace); +} +#endif + int main(int argc, char* argv[]) { brpc::FLAGS_idle_timeout_second = 0; testing::InitGoogleTest(&argc, argv); +#ifdef BRPC_BTHREAD_TRACER + // test using signal number other than SIGURG + bthread::FLAGS_signal_number_for_trace = SIGUSR2; +#endif return RUN_ALL_TESTS(); }