diff --git a/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk-tool/tool.cpp b/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk-tool/tool.cpp index f1da7f54a8a..f7b172e8b4a 100644 --- a/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk-tool/tool.cpp +++ b/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk-tool/tool.cpp @@ -3674,6 +3674,32 @@ rocprofv3_error_signal_handler(int signo, siginfo_t* info, void* ucontext) this_func, signo); + // Guard against recursive re-entry on the same thread. This occurs when a + // chained signal handler (e.g. one installed by the HSA runtime *after* + // rocprofv3 installed its own handler) invokes the previously-registered + // handler, which is this very function. Without this guard the std::call_once + // below would be re-entered by the same thread while it is still executing + // the call_once callable, which deadlocks (recursive use of std::once_flag is + // undefined behavior). When re-entered, the finalization has already been + // performed (or is in progress) by this thread, so we simply break the chain + // loop and proceed to termination. + static thread_local bool _in_signal_handler = false; + if(_in_signal_handler) + { + ROCP_WARNING << fmt::format( + "[PPID={}][PID={}][TID={}][{}] rocprofv3 re-entered signal handler for {} (chained " + "handler looped back); terminating", + this_ppid, + this_pid, + this_tid, + this_func, + signo); + if(signal_handler_exit) ::quick_exit(signo); + ::raise(signo); + return; + } + _in_signal_handler = true; + static auto _once = std::once_flag{}; std::call_once(_once, [&]() { auto get_children = [&this_pid]() { diff --git a/projects/rocprofiler-sdk/tests/rocprofv3/aborted-app/CMakeLists.txt b/projects/rocprofiler-sdk/tests/rocprofv3/aborted-app/CMakeLists.txt index ec186fa9e0e..aa8f7594339 100644 --- a/projects/rocprofiler-sdk/tests/rocprofv3/aborted-app/CMakeLists.txt +++ b/projects/rocprofiler-sdk/tests/rocprofv3/aborted-app/CMakeLists.txt @@ -18,9 +18,7 @@ string(REPLACE "LD_PRELOAD=" "ROCPROF_PRELOAD=" PRELOAD_ENV if(ROCPROFILER_MEMCHECK STREQUAL "ThreadSanitizer") set(IS_DISABLED ON) else() - # set(IS_DISABLED OFF) - set(IS_DISABLED ON) # this test is currently unstable so we are disabling it - # unconditionally for now + set(IS_DISABLED OFF) endif() # app-abort