Post

HN
Hacker News

Show HN: Sigwire – a live TUI switchboard for every signal on your Linux box

tail -f for signals. Every signal any process on the box raises β€” who sent it, who it hit, which signal, how it was raised ( kill(2) , the kernel, a POSIX timer), whether the target caught it and how long its handler ran, whether it tore a blocked syscall out with EINTR β€” decoded off the kernel's signal tracepoints and streamed live to your terminal. No strace -f on one pid, no ptrace , no cooperation from the processes involved.

sigwire turns the kernel's signal machinery into a live patchbay: each line is sender ──SIGNAL──▢ target , coloured by severity, tagged with how it was raised, whether the target caught it (and how long its handler ran), whether it interrupted a blocked syscall ( β†― EINTR read ), collapsed to Γ—N when something spams, and marked ☠ when it's a genuine killing blow. A side rail tallies what's flying across the wire; pause and pick a row to inspect the full picture β€” disposition, handler address, sigaction flags, and the signals the target was blocking at that instant.

Because it hooks the kernel's tracepoints , not any one process, a single run watches every signal on the host at once β€” your app, a supervisor, the kernel's own fault machinery β€” with none of them aware they're being traced.

Two sides of every signal. sigwire watches both signal:signal_generate (the sender's view β€” who raised what, the switchboard line) and signal:signal_deliver (the target's view β€” did it catch it, with which handler and flags, what was it blocking, and did it interrupt a syscall). Two more hooks β€” rt_sigreturn(2) and the syscall-exit tracepoint β€” time the handler and catch EINTR. It's all correlated back into one row. This split is also why the ☠ fatal count is deliberately conservative (see What counts as fatal ): generation happens before delivery, so the sender side can't know a signal's fate β€” only the delivery side can, and only for the cases it observes.

Nothing to configure β€” signals are constant background traffic on any box, so rows start landing at the top immediately. Want to make some yourself? kill -USR1 <pid> , Ctrl-C a foreground job, or start any managed runtime and watch its GC/scheduler ping its own threads ( β†― EINTR futex scrolling by).

The feed follows the newest signal by default; select a row or pause and it holds still while data keeps flowing underneath.