@@ -175,6 +175,13 @@ TEST(ThreadTeardownSafetyTest, SignalSafeAccessorReturnsNullWithoutInit) {
175175
176176// ── T-05: Concurrent signals during teardown stress ──────────────────────────
177177
178+ static std::atomic<int > g_t05_signal_count{0 };
179+
180+ static void t05_handler (int ) {
181+ (void )ProfiledThread::currentSignalSafe ();
182+ g_t05_signal_count.fetch_add (1 , std::memory_order_relaxed);
183+ }
184+
178185static void *t05_worker (void *) {
179186 ProfiledThread::initCurrentThread ();
180187 for (int i = 0 ; i < 10 ; ++i) {
@@ -184,14 +191,14 @@ static void *t05_worker(void *) {
184191 return nullptr ;
185192}
186193
187- // 20 threads × 5 rounds with signal spray; no crash expected.
188- // Signal dispositions are process-wide — set SIG_IGN once from the test body
189- // before spawning workers so concurrent SigGuard restore races cannot re-expose
190- // the default (terminate) disposition while a worker is mid-flight.
194+ // 20 threads × 5 rounds with signal spray; handler invocation is verified.
195+ // Signal dispositions are process-wide — install once from the test body so
196+ // no worker can race to restore SIG_DFL (terminate) mid-flight.
191197TEST (ThreadTeardownSafetyTest, ConcurrentSignalsDuringTeardownStress) {
192198 SigGuard gVtalrm (SIGVTALRM );
193199 SigGuard gProf (SIGPROF );
194- install_handler (SIGVTALRM , SIG_IGN );
200+ g_t05_signal_count.store (0 , std::memory_order_relaxed);
201+ install_handler (SIGVTALRM , t05_handler);
195202 install_handler (SIGPROF , SIG_IGN );
196203 for (int round = 0 ; round < 5 ; ++round) {
197204 std::vector<pthread_t > threads (20 );
@@ -202,6 +209,8 @@ TEST(ThreadTeardownSafetyTest, ConcurrentSignalsDuringTeardownStress) {
202209 pthread_join (tid, nullptr );
203210 }
204211 }
212+ EXPECT_GT (g_t05_signal_count.load (std::memory_order_relaxed), 0 )
213+ << " SIGVTALRM handler must have been invoked at least once" ;
205214}
206215
207216// ── T-06: SignalBlocker masks SIGPROF + SIGVTALRM and restores on exit ────────
@@ -335,6 +344,12 @@ TEST(ThreadTeardownSafetyTest, DoubleInitIsIdempotent) {
335344// ── T-09: High-frequency signals during thread churn ─────────────────────────
336345
337346static std::atomic<bool > g_t09_stop{false };
347+ static std::atomic<int > g_t09_signal_count{0 };
348+
349+ static void t09_handler (int ) {
350+ (void )ProfiledThread::currentSignalSafe ();
351+ g_t09_signal_count.fetch_add (1 , std::memory_order_relaxed);
352+ }
338353
339354static void *t09_injector (void *) {
340355 while (!g_t09_stop.load (std::memory_order_relaxed)) {
@@ -345,19 +360,19 @@ static void *t09_injector(void *) {
345360}
346361
347362static void *t09_worker (void *) {
348- SigGuard guard (SIGVTALRM );
349- install_handler (SIGVTALRM , SIG_IGN );
350363 ProfiledThread::initCurrentThread ();
351364 usleep (100 );
352365 ProfiledThread::release ();
353366 return nullptr ;
354367}
355368
356369// Mirrors DumpWhileChurningThreadsTest at native level: 100 short-lived threads
357- // under continuous SIGVTALRM injection must complete without crash.
370+ // under continuous SIGVTALRM injection must complete without crash; handler
371+ // invocation is verified.
358372TEST (ThreadTeardownSafetyTest, HighFrequencySignalsDuringThreadChurn) {
359373 SigGuard testGuard (SIGVTALRM );
360- install_handler (SIGVTALRM , SIG_IGN );
374+ g_t09_signal_count.store (0 , std::memory_order_relaxed);
375+ install_handler (SIGVTALRM , t09_handler);
361376
362377 g_t09_stop.store (false , std::memory_order_relaxed);
363378 pthread_t injector;
@@ -371,6 +386,8 @@ TEST(ThreadTeardownSafetyTest, HighFrequencySignalsDuringThreadChurn) {
371386
372387 g_t09_stop.store (true , std::memory_order_relaxed);
373388 pthread_join (injector, nullptr );
389+ EXPECT_GT (g_t09_signal_count.load (std::memory_order_relaxed), 0 )
390+ << " SIGVTALRM handler must have been invoked at least once" ;
374391}
375392
376393// ── T-10: CriticalSection reentrancy guard prevents double-entry ──────────────
0 commit comments