Ctrl+Z sends SIGSTOP to own PID instead of SIGTSTP to process group, breaks job control in containers/sandboxes

Resolved 💬 4 comments Opened Mar 5, 2026 by nikicat Closed May 23, 2026

Summary

Pressing Ctrl+Z in Claude Code sends SIGSTOP to its own PID (kill(<own_pid>, SIGSTOP)) instead of sending SIGTSTP to its process group (kill(0, SIGTSTP)). This breaks fg job control when Claude runs inside firejail (and likely any PID-namespaced sandbox).

Observed behavior

Inside a firejail sandbox, pressing Ctrl+Z:

  1. Claude prints: "Claude Code has been suspended. Run fg to bring Claude Code back."
  2. Running fg in the parent shell gives: fg: There are no suitable jobs
  3. The Claude process is killed (firejail's deterministic-shutdown sees the stopped child and terminates everything with SIGKILL)

Root cause (strace)

Attached strace to the Claude node process inside firejail and pressed Ctrl+Z:

2079493 kill(19, SIGSTOP)               = 0
2079493 --- SIGSTOP {si_signo=SIGSTOP, si_code=SI_USER, si_pid=19, si_uid=1000} ---
2079493 --- stopped by SIGSTOP ---
[... all threads stopped ...]
2079543 +++ killed by SIGKILL +++
[... all threads killed ...]

Two problems visible here:

  1. kill(19, SIGSTOP) — sends the signal to PID 19 (Claude's own PID inside firejail's PID namespace). Since firejail is outside the namespace, it never receives the stop signal. The parent shell (fish) never sees a stopped job, so fg finds nothing.
  1. SIGSTOP instead of SIGTSTPSIGSTOP cannot be caught or handled, which is more aggressive than necessary for job control. Standard terminal suspension uses SIGTSTP, which is catchable and what shells expect.

Expected behavior

Claude should send SIGTSTP to its process group so the signal propagates to the sandbox wrapper process:

process.kill(0, 'SIGTSTP')   // kill(0, SIGTSTP) — targets entire process group

instead of:

process.kill(process.pid, 'SIGSTOP')  // kill(<pid>, SIGSTOP) — only targets self

This would allow firejail (and other wrappers) to also stop, making the parent shell see a suspended job that fg can resume.

Environment

  • Claude Code via /usr/bin/claude
  • Shell: fish
  • Sandbox: firejail with PID namespace (default)
  • OS: Linux 6.18.13-zen1-1-zen (Arch)

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗