diff --git a/ddprof-lib/src/main/cpp/counters.h b/ddprof-lib/src/main/cpp/counters.h index 623e2c95a..8817af541 100644 --- a/ddprof-lib/src/main/cpp/counters.h +++ b/ddprof-lib/src/main/cpp/counters.h @@ -149,10 +149,10 @@ #endif // Fault-injection + debug only: faults injected while the current thread was -// NOT inside a walkVM longjmp-protected region. Such a site relies solely on +// NOT inside a walkVM siglongjmp-protected region. Such a site relies solely on // safefetch (or would genuinely crash if the poisoned pointer is raw-dereferenced // outside any recovery), so a non-zero value flags injection sites that are not -// covered by longjmp protection. Compiled in only when both __FAULT_INJECTION__ +// covered by siglongjmp protection. Compiled in only when both __FAULT_INJECTION__ // and DEBUG are defined. #if defined(__FAULT_INJECTION__) && defined(DEBUG) #define DD_COUNTER_TABLE_FI_DEBUG(X) \ @@ -162,7 +162,7 @@ #endif // Debug-only counters: SafeAccess reads/copies issued while the thread is -// already inside a walkVM longjmp-protected region (redundant safefetch +// already inside a walkVM siglongjmp-protected region (redundant safefetch // overhead). Not compiled into release builds at all, so they occupy no enum // slot and add no storage there. #ifdef DEBUG diff --git a/ddprof-lib/src/main/cpp/faultInjection.cpp b/ddprof-lib/src/main/cpp/faultInjection.cpp index c42298ec2..d61be77b6 100644 --- a/ddprof-lib/src/main/cpp/faultInjection.cpp +++ b/ddprof-lib/src/main/cpp/faultInjection.cpp @@ -89,7 +89,7 @@ bool shouldFire(u64 threshold, const char* fn) { // place that counts an actually-injected fault. Counters::increment(FAULTS_INJECTED); #ifdef DEBUG - // Flag injections fired at a site with no walkVM longjmp protection active: + // Flag injections fired at a site with no walkVM siglongjmp protection active: // recovery there depends entirely on safefetch, and a raw deref would crash. ProfiledThread* t = ProfiledThread::current(); // never allocates if (t == nullptr || !t->isProtected()) { diff --git a/ddprof-lib/src/main/cpp/faultInjection.h b/ddprof-lib/src/main/cpp/faultInjection.h index f3e5ad1b6..e19f4bb1e 100644 --- a/ddprof-lib/src/main/cpp/faultInjection.h +++ b/ddprof-lib/src/main/cpp/faultInjection.h @@ -20,7 +20,7 @@ // site (VMStructs::at, walkVM, walkFP, walkDwarf). When __FAULT_INJECTION__ is // defined, each wrapped expression, with the tier's probability, is replaced by // a deliberately bad address (so the load faults and the profiler's recovery -// path — SafeAccess safefetch or walkVM's setjmp/longjmp — is exercised) or a +// path — SafeAccess safefetch or walkVM's sigsetjmp/siglongjmp — is exercised) or a // random int/long value. When the flag is NOT defined, every macro is a strict // identity: it expands to exactly the parenthesized original expression, with // unchanged type and value category and zero runtime cost. diff --git a/ddprof-lib/src/main/cpp/guards.h b/ddprof-lib/src/main/cpp/guards.h index 4addd8d39..18bc4fbed 100644 --- a/ddprof-lib/src/main/cpp/guards.h +++ b/ddprof-lib/src/main/cpp/guards.h @@ -90,14 +90,14 @@ class SignalHandlerScope { #define SIGNAL_HANDLER_GUARD() SignalHandlerScope _signal_handler_scope // Manually release the most recent SIGNAL_HANDLER_GUARD() before chaining to -// another handler that may longjmp through us (e.g. J9's SIGSEGV null-pointer +// another handler that may siglongjmp through us (e.g. J9's SIGSEGV null-pointer // check handler). After release(), depth has already been decremented; the // destructor becomes a no-op. #define SIGNAL_HANDLER_GUARD_RELEASE() _signal_handler_scope.release() -// Compensate for a longjmp that bypassed a SignalHandlerScope's destructor. -// Call at the setjmp landing point AFTER a known longjmp originated from -// within a signal handler frame (e.g. HotSpot's checkFault → longjmp recovery +// Compensate for a siglongjmp that bypassed a SignalHandlerScope's destructor. +// Call at the sigsetjmp landing point AFTER a known siglongjmp originated from +// within a signal handler frame (e.g. HotSpot's checkFault → siglongjmp recovery // in walkVM). void signalHandlerUnwindAfterLongjmp(); #define SIGNAL_HANDLER_UNWIND_AFTER_LONGJMP() signalHandlerUnwindAfterLongjmp() diff --git a/ddprof-lib/src/main/cpp/hotspot/hotspotSupport.cpp b/ddprof-lib/src/main/cpp/hotspot/hotspotSupport.cpp index 9e4ad7283..2b319b100 100644 --- a/ddprof-lib/src/main/cpp/hotspot/hotspotSupport.cpp +++ b/ddprof-lib/src/main/cpp/hotspot/hotspotSupport.cpp @@ -248,19 +248,19 @@ __attribute__((no_sanitize("address"))) int HotspotSupport::walkVM(void* ucontex int bcp_offset = InterpreterFrame::bcp_offset(); - jmp_buf crash_protection_ctx; - // Chaining jmp_buf + sigjmp_buf crash_protection_ctx; + // Chaining sigjmp_buf // A non-signal-based-sampler can be interrupted by signal based sampler, // then we end up with multiple HotspotSupport::walkVM() calls on stack, - // each one sets up jmp_buf, they need to be chained to jump back to + // each one sets up sigjmp_buf, they need to be chained to jump back to // correct location. - jmp_buf* prev_jmp_buf = prof_thread->getJmpCtx(); - // Should be preserved across setjmp/longjmp + sigjmp_buf* prev_jmp_buf = prof_thread->getJmpCtx(); + // Should be preserved across sigsetjmp/siglongjmp volatile int depth = 0; int actual_max_depth = truncated ? max_depth + 1 : max_depth; - if (setjmp(crash_protection_ctx) != 0) { - // checkFault() does a longjmp from inside segvHandler, bypassing + if (sigsetjmp(crash_protection_ctx, 1) != 0) { + // checkFault() does a siglongjmp from inside segvHandler, bypassing // segvHandler's SignalHandlerScope destructor. Compensate. SIGNAL_HANDLER_UNWIND_AFTER_LONGJMP(); prof_thread->setJmpCtx(prev_jmp_buf); @@ -378,7 +378,7 @@ __attribute__((no_sanitize("address"))) int HotspotSupport::walkVM(void* ucontex } // entry_fp has been range-checked by isValidFP above; any remaining // SIGSEGV from a stale/concurrently-freed pointer is caught by the - // setjmp crash protection in walkVM (checkFault -> longjmp). + // sigsetjmp crash protection in walkVM (checkFault -> siglongjmp). uintptr_t* carrier_fp_addr = (uintptr_t*)INJECT_FAULT_ADDRESS_UNLIKELY(entry_fp); uintptr_t carrier_fp = *carrier_fp_addr; const void* carrier_pc = ((const void**)carrier_fp_addr)[FRAME_PC_SLOT]; @@ -414,8 +414,8 @@ __attribute__((no_sanitize("address"))) int HotspotSupport::walkVM(void* ucontex // while PC is still in JVM stubs (JavaCalls, method entry/exit), we see CodeHeap // code without VMThread context. // - // Without vm_thread, crash protection via setjmp/longjmp cannot work - // (checkFault() needs vm_thread->exception() to longjmp). Any memory dereference in interpreter + // Without vm_thread, crash protection via sigsetjmp/siglongjmp cannot work + // (checkFault() needs vm_thread->exception() to siglongjmp). Any memory dereference in interpreter // frame handling or NMethod validation would crash the process with unrecoverable SEGV. // // The missing VMThread is a timing issue during thread lifecycle. @@ -984,14 +984,14 @@ void HotspotSupport::checkFault(ProfiledThread* thrd) { return; } - // Check if longjmp is setup for this thread + // Check if siglongjmp is set up for this thread if (!thrd->isProtected()) { return; } thrd->resetCrashHandler(); Counters::increment(WALKVM_LONGJMP_RECOVERED); - longjmp(*thrd->getJmpCtx(), 1); + siglongjmp(*thrd->getJmpCtx(), 1); } int HotspotSupport::getJavaTraceAsync(void *ucontext, ASGCT_CallFrame *frames, diff --git a/ddprof-lib/src/main/cpp/hotspot/vmStructs.h b/ddprof-lib/src/main/cpp/hotspot/vmStructs.h index 139d430a3..e09d035bb 100644 --- a/ddprof-lib/src/main/cpp/hotspot/vmStructs.h +++ b/ddprof-lib/src/main/cpp/hotspot/vmStructs.h @@ -33,11 +33,11 @@ class VMNMethod; // During stack walking in the profiler's signal handler, GC or class unloading // on another thread can free VMNMethod/VMMethod memory concurrently, making // pointers stale between the readability check and the actual dereference. -// In release builds the setjmp/longjmp crash protection in walkVM catches the +// In release builds the sigsetjmp/siglongjmp crash protection in walkVM catches the // resulting SIGSEGV. In debug builds the assert(isReadable) fires first, // sending SIGABRT which is uncatchable by crash protection. // When crash protection is active the assert is redundant — any bad read will -// be caught by the SIGSEGV handler and recovered via longjmp — so we skip it. +// be caught by the SIGSEGV handler and recovered via siglongjmp — so we skip it. // // Defined at the bottom of this file after VMThread is declared so that the // VMThread fallback path (isExceptionActive) is accessible without forward- diff --git a/ddprof-lib/src/main/cpp/profiler.cpp b/ddprof-lib/src/main/cpp/profiler.cpp index 51769089a..7c631b002 100644 --- a/ddprof-lib/src/main/cpp/profiler.cpp +++ b/ddprof-lib/src/main/cpp/profiler.cpp @@ -927,15 +927,15 @@ void Profiler::disableEngines() { void Profiler::segvHandler(int signo, siginfo_t *siginfo, void *ucontext) { // J9 installs a SIGSEGV handler that uses siglongjmp() to recover from // null-pointer-check faults during normal Java execution. When we chain to - // it, that longjmp unwinds past our stack frame and skips the RAII + // it, that siglongjmp unwinds past our stack frame and skips the RAII // destructor, permanently leaking depth on the thread. Release the guard // before chaining so depth is correct whether the chained handler returns - // or longjmps. + // or siglongjmps. // // Sanitizer-coverage note: this also means depth == 0 inside the chained // handler, so DEBUG_ASSERT_NOT_IN_SIGNAL() will NOT fire for AS-unsafe // code reachable from a chained handler that returns normally. This is - // the lesser of two evils — leaking depth on longjmp would silently + // the lesser of two evils — leaking depth on siglongjmp would silently // break the production deferred-refresh gate, while the sanitizer gap // is bounded to third-party signal handler code we don't own. SIGNAL_HANDLER_GUARD(); @@ -943,7 +943,7 @@ void Profiler::segvHandler(int signo, siginfo_t *siginfo, void *ucontext) { return; // Handled — destructor decrements depth } SIGNAL_HANDLER_GUARD_RELEASE(); - // Not handled, chain to next handler (may longjmp; never return through us) + // Not handled, chain to next handler (may siglongjmp; never return through us) SigAction chain = OS::getSegvChainTarget(); if (chain != nullptr) { chain(signo, siginfo, ucontext); @@ -954,7 +954,7 @@ void Profiler::segvHandler(int signo, siginfo_t *siginfo, void *ucontext) { void Profiler::busHandler(int signo, siginfo_t *siginfo, void *ucontext) { // See segvHandler: release before chaining in case the chained handler - // longjmps through us. + // siglongjmps through us. SIGNAL_HANDLER_GUARD(); if (crashHandlerInternal(signo, siginfo, ucontext)) { return; // Handled — destructor decrements depth @@ -982,7 +982,7 @@ int Profiler::crashHandlerInternal(int signo, siginfo_t *siginfo, void *ucontext // Reentrancy protection: use TLS-based tracking if available. // If TLS is not available, the thread is not protected by - // longjmp, so bail out. + // siglongjmp, so bail out. bool have_tls_protection = false; if (thrd != nullptr) { if (!thrd->enterCrashHandler()) { @@ -1015,7 +1015,7 @@ int Profiler::crashHandlerInternal(int signo, siginfo_t *siginfo, void *ucontext // the following checks require vmstructs and therefore HotSpot // HotspotSupport::checkFault has its own check if we're in a protected stack walk. - // If the fault is from our protected walk, it will longjmp and never return. + // If the fault is from our protected walk, it will siglongjmp and never return. // If it returns, the fault wasn't from our code. HotspotSupport::checkFault(thrd); diff --git a/ddprof-lib/src/main/cpp/safeAccess.h b/ddprof-lib/src/main/cpp/safeAccess.h index 7d78f2cc6..564743b15 100644 --- a/ddprof-lib/src/main/cpp/safeAccess.h +++ b/ddprof-lib/src/main/cpp/safeAccess.h @@ -119,9 +119,9 @@ class SafeAccess { #ifdef DEBUG private: // Debug diagnostic: bump a counter when a SafeAccess read/copy is issued while - // the current thread is already inside a walkVM longjmp-protected region, where + // the current thread is already inside a walkVM siglongjmp-protected region, where // the safefetch/safecopy overhead is redundant (a fault there is caught by the - // longjmp anyway). Defined out-of-line in safeAccess.cpp so this widely-included + // siglongjmp anyway). Defined out-of-line in safeAccess.cpp so this widely-included // header need not pull in threadLocalData.h / counters.h. isCopy selects the // SAFECOPY_WHILE_PROTECTED vs SAFEFETCH_WHILE_PROTECTED counter. static void countIfLongjmpProtected(bool isCopy); diff --git a/ddprof-lib/src/main/cpp/threadLocalData.h b/ddprof-lib/src/main/cpp/threadLocalData.h index 3f143efa6..293a8c15a 100644 --- a/ddprof-lib/src/main/cpp/threadLocalData.h +++ b/ddprof-lib/src/main/cpp/threadLocalData.h @@ -58,12 +58,12 @@ class ProfiledThread : public ThreadLocalData { static void freeValue(void* value); static ThreadLocal _current_thread; - // longjmp buffer. Used by hotspot only at this moment. + // siglongjmp buffer. Used by hotspot only at this moment. // Published in walkVM() and consumed in checkFault() from an asynchronous // SEGV-handler context on the same thread; atomic makes the publish/observe // ordering explicit instead of relying on plain load/store, matching how // _crash_depth is hardened below. - std::atomic _jmp_buf; + std::atomic _jmp_buf; u64 _pc; u64 _sp; @@ -238,11 +238,11 @@ class ProfiledThread : public ThreadLocalData { return __atomic_load_n(&_crash_depth, __ATOMIC_RELAXED) > CRASH_HANDLER_NESTING_LIMIT; } - inline void setJmpCtx(jmp_buf* buf) { - _jmp_buf = buf; + inline void setJmpCtx(sigjmp_buf* buf) { + _jmp_buf = buf; } - inline jmp_buf* getJmpCtx() const { + inline sigjmp_buf* getJmpCtx() const { return _jmp_buf; } diff --git a/ddprof-lib/src/test/cpp/faultInjection_ut.cpp b/ddprof-lib/src/test/cpp/faultInjection_ut.cpp index abb81b8ed..d1d25c250 100644 --- a/ddprof-lib/src/test/cpp/faultInjection_ut.cpp +++ b/ddprof-lib/src/test/cpp/faultInjection_ut.cpp @@ -51,7 +51,7 @@ TEST(FaultInjectionTest, DisabledValueMacrosAreIdentity) { #else // __FAULT_INJECTION__ enabled (built under -PenableFaultInjection) -// Chain: safefetch recovery first, then walkVM setjmp/longjmp recovery, then +// Chain: safefetch recovery first, then walkVM sigsetjmp/siglongjmp recovery, then // the crash handler as a last resort so a genuine bug still produces a report. static void (*orig_segvHandler)(int, siginfo_t*, void*); static void (*orig_busHandler)(int, siginfo_t*, void*); @@ -60,7 +60,7 @@ static void fi_signal_wrapper(int signo, siginfo_t* siginfo, void* context) { if (SafeAccess::handle_safefetch(signo, context)) { return; // safefetch load recovered; PC already rewritten to _cont. } - HotspotSupport::checkFault(ProfiledThread::current()); // longjmp if protected + HotspotSupport::checkFault(ProfiledThread::current()); // siglongjmp if protected // Not protected and not a safefetch fault — real crash. if (signo == SIGBUS && orig_busHandler != nullptr) { orig_busHandler(signo, siginfo, context); @@ -144,8 +144,8 @@ TEST_F(FaultInjectionTest, SafeAccessRecoversFromInjectedFault) { } // (c2) walkVM path: a raw dereference of an injected poison pointer must be -// caught by the setjmp/longjmp crash protection, returning control to setjmp. -TEST_F(FaultInjectionTest, WalkVmSetjmpRecoversFromInjectedFault) { +// caught by the sigsetjmp/siglongjmp crash protection, returning control to sigsetjmp. +TEST_F(FaultInjectionTest, WalkVmSigsetjmpRecoversFromInjectedFault) { ProfiledThread* t = ProfiledThread::current(); ASSERT_NE(t, nullptr); @@ -155,9 +155,9 @@ TEST_F(FaultInjectionTest, WalkVmSetjmpRecoversFromInjectedFault) { volatile size_t reads = 0; volatile size_t faults = 0; - jmp_buf ctx; - if (setjmp(ctx) != 0) { - recovered = true; // returned here via checkFault -> longjmp + sigjmp_buf ctx; + if (sigsetjmp(ctx, 1) != 0) { + recovered = true; // returned here via checkFault -> siglongjmp faults++; } t->setJmpCtx(&ctx); @@ -174,8 +174,8 @@ TEST_F(FaultInjectionTest, WalkVmSetjmpRecoversFromInjectedFault) { // We should have observed a recovered fault, or the loop completed cleanly. The // essential assertion is that the process did not die and, when a fault was - // injected, setjmp regained control. - EXPECT_GT(faults, 0u) << "expected at least one injected fault to longjmp-recover"; + // injected, sigsetjmp regained control. + EXPECT_GT(faults, 0u) << "expected at least one injected fault to siglongjmp-recover"; EXPECT_TRUE(recovered); SUCCEED(); } diff --git a/ddprof-lib/src/test/cpp/hotspot_crash_protection_ut.cpp b/ddprof-lib/src/test/cpp/hotspot_crash_protection_ut.cpp index 1f434aa4b..be1dcab61 100644 --- a/ddprof-lib/src/test/cpp/hotspot_crash_protection_ut.cpp +++ b/ddprof-lib/src/test/cpp/hotspot_crash_protection_ut.cpp @@ -10,13 +10,13 @@ * dereference JavaThread-only fields (anchor, vframe_top, …) on such threads. * VMThread::isJavaThread() provides the gate. * - * Crash recovery inside walkVM relies on setjmp/longjmp: - * 1. walkVM stores a jmp_buf* on ProfiledThread (setJmpCtx/getJmpCtx), + * Crash recovery inside walkVM relies on sigsetjmp/siglongjmp: + * 1. walkVM stores a sigjmp_buf* on ProfiledThread (setJmpCtx/getJmpCtx), * chaining it with whatever context was already installed so a * signal-based sampler interrupting a non-signal-based sampler's own * in-flight walkVM() call doesn't clobber the outer call's context. * 2. If a fault fires during the walk, checkFault() detects the live - * context via ProfiledThread::isProtected() and calls longjmp() to + * context via ProfiledThread::isProtected() and calls siglongjmp() to * unwind through whatever context is currently installed. * 3. ProfiledThread tracks nested crash-handler depth so recursive faults * (e.g. wall-clock signal inside a crash handler) are capped safely. @@ -24,7 +24,7 @@ * Tests cover: * A. ProfiledThread thread-type classification (isJavaThread fast path) * B. Crash-handler nesting depth (ProfiledThread crash handler state) - * C. jmp_buf chaining across nested/interrupted walkVM() calls + * C. sigjmp_buf chaining across nested/interrupted walkVM() calls */ #include @@ -115,7 +115,7 @@ TEST_F(ProfiledThreadTypeTest, FastPathReturnsFalseForNonJavaThread) { // Profiler::crashHandlerInternal calls: // enterCrashHandler() — on entry, returns false if limit reached // exitCrashHandler() — on normal exit -// resetCrashHandler() — from checkFault before longjmp to unwind all +// resetCrashHandler() — from checkFault before siglongjmp to unwind all // nesting at once // --------------------------------------------------------------------------- @@ -160,7 +160,7 @@ TEST_F(CrashHandlerNestingTest, LimitBlocksFurtherEntry) { } } -// resetCrashHandler() is called by checkFault() before longjmp so that the +// resetCrashHandler() is called by checkFault() before siglongjmp so that the // landing pad in walkVM starts with a clean nesting count. TEST_F(CrashHandlerNestingTest, ResetAllowsEntryAfterDeepNesting) { for (u32 i = 0; i < ProfiledThread::CRASH_HANDLER_NESTING_LIMIT; i++) { @@ -190,16 +190,16 @@ TEST_F(CrashHandlerNestingTest, IsDeepOnlyAboveLimit) { } // --------------------------------------------------------------------------- -// C. jmp_buf chaining (ProfiledThread::setJmpCtx/getJmpCtx/isProtected) +// C. sigjmp_buf chaining (ProfiledThread::setJmpCtx/getJmpCtx/isProtected) // // A non-signal-based sampler's walkVM() call can itself be interrupted by a // signal-based sampler, putting two walkVM() frames on the same thread's // stack. Each frame follows the same protocol: -// jmp_buf* prev = prof_thread->getJmpCtx(); // save whatever was there +// sigjmp_buf* prev = prof_thread->getJmpCtx(); // save whatever was there // prof_thread->setJmpCtx(&my_ctx); // install this frame's ctx // ... walk ... // prof_thread->setJmpCtx(prev); // restore on every exit path -// checkFault() always longjmps through whatever is currently installed +// checkFault() always siglongjmps through whatever is currently installed // (thrd->getJmpCtx()), so the inner frame must never leave the outer frame's // context installed while the inner frame is doing its own protected work, // and must always hand it back — via normal completion or fault recovery — @@ -227,7 +227,7 @@ TEST_F(JmpCtxChainingTest, InitiallyUnprotected) { } TEST_F(JmpCtxChainingTest, SetAndGetRoundTrip) { - jmp_buf ctx; + sigjmp_buf ctx; _pt->setJmpCtx(&ctx); EXPECT_TRUE(_pt->isProtected()); EXPECT_EQ(&ctx, _pt->getJmpCtx()); @@ -235,8 +235,8 @@ TEST_F(JmpCtxChainingTest, SetAndGetRoundTrip) { // Replicates a single walkVM() call's save/install/restore around its body. TEST_F(JmpCtxChainingTest, SingleFrameRestoresPreviousOnExit) { - jmp_buf outer; - jmp_buf* prev = _pt->getJmpCtx(); // nullptr: no enclosing walkVM() call + sigjmp_buf outer; + sigjmp_buf* prev = _pt->getJmpCtx(); // nullptr: no enclosing walkVM() call ASSERT_EQ(nullptr, prev); _pt->setJmpCtx(&outer); @@ -250,11 +250,11 @@ TEST_F(JmpCtxChainingTest, SingleFrameRestoresPreviousOnExit) { // Replicates two nested walkVM() calls: a signal-based sampler interrupting a // non-signal-based sampler's own in-flight walkVM(). The inner call must -// chain off the outer's jmp_buf*, install its own, and hand the outer's back +// chain off the outer's sigjmp_buf*, install its own, and hand the outer's back // on its way out — leaving the outer frame's context exactly as it left it. TEST_F(JmpCtxChainingTest, NestedFramesChainAndUnwindInOrder) { - jmp_buf outer_ctx; - jmp_buf* outer_prev = _pt->getJmpCtx(); + sigjmp_buf outer_ctx; + sigjmp_buf* outer_prev = _pt->getJmpCtx(); ASSERT_EQ(nullptr, outer_prev); _pt->setJmpCtx(&outer_ctx); EXPECT_EQ(&outer_ctx, _pt->getJmpCtx()); @@ -262,8 +262,8 @@ TEST_F(JmpCtxChainingTest, NestedFramesChainAndUnwindInOrder) { { // Inner walkVM() call, as if a signal fired while the outer one was // mid-walk. - jmp_buf inner_ctx; - jmp_buf* inner_prev = _pt->getJmpCtx(); + sigjmp_buf inner_ctx; + sigjmp_buf* inner_prev = _pt->getJmpCtx(); EXPECT_EQ(&outer_ctx, inner_prev); // chained off the outer frame _pt->setJmpCtx(&inner_ctx); @@ -280,36 +280,36 @@ TEST_F(JmpCtxChainingTest, NestedFramesChainAndUnwindInOrder) { EXPECT_EQ(nullptr, _pt->getJmpCtx()); } -// End-to-end with real setjmp/longjmp: a fault inside the inner frame must +// End-to-end with real sigsetjmp/siglongjmp: a fault inside the inner frame must // land in the inner frame's own recovery branch — checkFault() always -// longjmps through whatever is currently installed — and once the inner +// siglongjmps through whatever is currently installed — and once the inner // frame has recovered and restored the outer's context, the outer frame must // be left exactly as it was, never having been unwound itself. TEST_F(JmpCtxChainingTest, FaultInInnerFrameDoesNotDisturbOuterFrame) { - jmp_buf outer_ctx; - jmp_buf* outer_prev = _pt->getJmpCtx(); + sigjmp_buf outer_ctx; + sigjmp_buf* outer_prev = _pt->getJmpCtx(); int outer_landed = 0; int inner_landed = 0; - if (setjmp(outer_ctx) != 0) { + if (sigsetjmp(outer_ctx, 1) != 0) { outer_landed++; } else { _pt->setJmpCtx(&outer_ctx); // --- inner "walkVM" call, interrupted mid-flight by a fault --- - jmp_buf inner_ctx; - jmp_buf* inner_prev = _pt->getJmpCtx(); + sigjmp_buf inner_ctx; + sigjmp_buf* inner_prev = _pt->getJmpCtx(); ASSERT_EQ(&outer_ctx, inner_prev); - if (setjmp(inner_ctx) != 0) { + if (sigsetjmp(inner_ctx, 1) != 0) { inner_landed++; _pt->setJmpCtx(inner_prev); } else { _pt->setJmpCtx(&inner_ctx); - // Simulate checkFault(): longjmp through whatever is currently + // Simulate checkFault(): siglongjmp through whatever is currently // installed — this must hit the inner frame, not the outer. - longjmp(*_pt->getJmpCtx(), 1); - FAIL() << "unreachable: longjmp does not return"; + siglongjmp(*_pt->getJmpCtx(), 1); + FAIL() << "unreachable: siglongjmp does not return"; } // --- inner call has returned normally after recovering --- @@ -328,7 +328,7 @@ TEST_F(JmpCtxChainingTest, FaultInInnerFrameDoesNotDisturbOuterFrame) { // D. HotspotSupport::checkFault() guard clauses // // This gtest binary has no live JVM attached, so JVMThread is not initialized -// and the longjmp path can't be exercised end-to-end here. +// and the siglongjmp path can't be exercised end-to-end here. // These tests still call the real checkFault() (not a replica) to lock down // its early-return guard: a null ProfiledThread* // ---------------------------------------------------------------------------