kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit 47416641591997ccc7327528e9c972571436b9bc
parent a2abf09a805ee4916fbcdd926a9d444cbc34229d
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Mon, 11 May 2026 14:17:17 -0700

dbg: copy CfreeDbgSignalOps in signals_install, not the caller pointer

The signal handler dereferenced g_dbg_ops, which pointed at a stack-local
in cfree_jit_session_new. By the time the worker took its first BRK that
frame was gone, so the handler jumped to garbage and the REPL hung
waiting on ev_stop (or surfaced as Trace/BPT trap: 5).

Diffstat:
Mdriver/env.c | 18+++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/driver/env.c b/driver/env.c @@ -452,7 +452,8 @@ static CfreeExecMem g_execmem_posix; /* page_size set in driver_env_init */ * handler reads these from async-signal context; both writes happen in * signals_install before any signal can arrive, both clears happen in * signals_uninstall after restoring SIG_DFL. */ -static const CfreeDbgSignalOps* g_dbg_ops; +static CfreeDbgSignalOps g_dbg_ops; +static int g_dbg_ops_set; static void* g_dbg_session; static pthread_t g_dbg_worker_tid; static int g_dbg_worker_tid_valid; @@ -643,8 +644,8 @@ static void dbg_signal_handler(int signo, siginfo_t* si, void* ucv) { /* Only the registered worker thread participates in stop-the-world. * Faults on other threads (e.g. the REPL) fall through to the default. */ if (!g_dbg_worker_tid_valid || - !pthread_equal(pthread_self(), g_dbg_worker_tid) || !g_dbg_ops || - !g_dbg_ops->on_fault) { + !pthread_equal(pthread_self(), g_dbg_worker_tid) || !g_dbg_ops_set || + !g_dbg_ops.on_fault) { int i; for (i = 0; i < DBG_NSIGS; ++i) { if (g_dbg_signos[i] == signo) { @@ -657,7 +658,7 @@ static void dbg_signal_handler(int signo, siginfo_t* si, void* ucv) { } dbg_ucontext_to_frame(uc, &frame); - rc = g_dbg_ops->on_fault(g_dbg_session, signo, &frame); + rc = g_dbg_ops.on_fault(g_dbg_session, signo, &frame); if (rc != 0) { /* Session declined to handle: restore default and re-raise so the * host produces a core dump for the original cause. */ @@ -680,7 +681,8 @@ static int dbg_signals_install(void* user, const CfreeDbgSignalOps* ops, int i; (void)user; if (g_dbg_installed) return 1; - g_dbg_ops = ops; + g_dbg_ops = *ops; + g_dbg_ops_set = 1; g_dbg_session = session; memset(&sa, 0, sizeof(sa)); @@ -696,7 +698,8 @@ static int dbg_signals_install(void* user, const CfreeDbgSignalOps* ops, /* Roll back what we installed. */ int j; for (j = 0; j < i; ++j) sigaction(g_dbg_signos[j], &g_dbg_prev_sa[j], NULL); - g_dbg_ops = NULL; + memset(&g_dbg_ops, 0, sizeof(g_dbg_ops)); + g_dbg_ops_set = 0; g_dbg_session = NULL; return 1; } @@ -712,7 +715,8 @@ static void dbg_signals_uninstall(void* user) { for (i = 0; i < DBG_NSIGS; ++i) sigaction(g_dbg_signos[i], &g_dbg_prev_sa[i], NULL); g_dbg_installed = 0; - g_dbg_ops = NULL; + memset(&g_dbg_ops, 0, sizeof(g_dbg_ops)); + g_dbg_ops_set = 0; g_dbg_session = NULL; }