
2026/07/14 5:07
Sigwire:Linux マシンの全ての信号に対するライブ TUI スイッチボードに関する投稿です
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
Sigwire は、侵入的なツール(
strace または ptrace など)を使わずに、カーネルレベルの信号 tracepoint をデコードして送信元、ターゲット、信号タイプ、原因、および disposition というリアルタイムの詳細情報をターミナルにストリーミングすることで、信号デバッグを革新します。 bounded ring buffer を使用したパッシブな tracepoint 書き込みを利用し、高パフォーマンスを実現しており、rt_sigreturn と syscall-extracepoints にフックしてハンドラーの継続時間を測定し、EINTR 中断を検出しながらも negligible なスロウドラウンを確保します。本ツールは Linux カーネルの BTF サポート(CONFIG_DEBUG_INFO_BTF)と yeet デーモンに依存し、効率的なprivileged component のロードを実現しています。インターフェースはインタラクティブな制御を提供しており、ユーザーは一時停止/再開 (p · Space)、行移動 (↑/↓, k/j)、ファジーフィルター (/)、EINTR だけの表示 (e)、シグナルのミュート(トグル、グローバルビット操作、例:デフォルトでは SIGCHLD、SIGURG、SIGWINCH をミュート)、終了 (q) を実行できます。各行にはタイミング、送信元、重大度コード付きの信号タイプ(色は致命傷またはキル可能な信号に対してホットレッドから他に対してバイオレット/グレーまで範囲)、ターゲット、およびソース/EINTR 状態に関する注釈が表示されます。厳格な fatal カウンター(☠)は、SIGKILL やカーネルによるコアダンプイベントなどのつかえないシグナルだけを追跡します。裏側では、BPF プログラム(sigwire.bpf.c、deliver.bpf.c)が (target tid, signal) マップを介して相関するプローブにリンクし、JS プローブがこのマップをバインドしています。インストールは簡単な curl コマンドによる yeet デーモンのインストールで行うのが簡単ですが、開発者は Sigwire が可観測性のみを提供し、シグナルのブロックや遅延を行うことができず、タイミングはカーネルフレームの継続時間のみを反映する点に注意する必要があります。品質保証には verifier 互換性チェック(make veristat)および LVH/QEMU VM で Cilium イメージを使用して行うマテックステストが含まれます。本文
sigwire: カーネル信号処理の可視化ライブパッチボード
概要
sigwire は、ホスト上のあらゆるプロセスから放出されるすべての信号をリアルタイムでキャプチャし、ターミナルにストリーミング表示するツールです。
- 対象範囲: ホスト上の全プロセス(特定の PID 限定ではありません)。
- 追跡方法:
のようにターゲットの協力が不要であり、strace -f
を使用しません。ptrace - 可視化方式: カーネルの信号処理を**「ライブパッチボード」**として可視化します。
表示の特徴
各情報は以下の要素で構成され、Severity(優先度)に応じた色付けが施されます。
- 発生方法のタグ: システムコール名などの情報源を示します。
- 処理結果: ターゲットがハンドラを呼び出したか(実行時間を含む)、デフォルト動作に陥ったか、無視したかを判定します。
- システムコール中断 (
): 待機中のシステムコールが信号で切断されたことを示します(例:EINTR
)。↯ EINTR read - スパム統合: 連続した同一信号は
として表示し、画面を汚しません。×N - 致命傷識別: 本物の致命的な攻撃には☠記号が表示されます。
**サイドレール(右パネル)**では、「ワイヤー(信号の流れ)」を横断する集計情報が確認できます。行を選択または一時停止すると、その瞬間の詳細情報(ディスポジション、ハンドラアドレス、
sigaction フラグ、ブロックされていた信号など)を表示可能です。
動作原理:2 つの視点
sigwire は以下の 2 つの観点からの情報を統合して表示します。
- 生成側 (
)signal:signal_generate- 誰が何を発射したか(送信者の視点)。
- カーネルやアプリによるシグナル発生源を追跡します。
- 受領側 (
)signal:signal_deliver- ターゲットがどう反応したか(ハンドラの実行、ブロック状況、システムコールの中断)。
これに加え、以下のフックを使用して精度を向上させています:
とrt_sigreturn(2)
トレースポイントを用いてハンドラの走行時間を計測。syscall-exit
の発生を検出。EINTR
これらはすべて 1 つの行に相関付けられており、表示されています。☠「致命的なカウント」は保守的に設定されており、意図的に慎重に判定します。
クイックスタート (Linux)
インストール
特別な設定は不要です。信号は常に背景トラフィックとして存在するため、即座に表示が始まります。
curl -fsSL https://yeet.cx | sh # yeet デモンをインストール(初回のみ) yeet run github:yeet-src/sigwire # ダッシュボードを実行
サンプル出力(生成された信号の例)
画面の上部に新しいデータが表示されます。
| WHEN | SENDER (送信者) | SIGNAL | TARGET (ターゲット) | NOTE (注釈) |
|---|---|---|---|---|
| | | | |
| | | | |
| | | | |
| | | |
コントロールキーボード操作
フィードはデフォルトで最新情報のみを表示しますが、一時停止して詳細を確認できます。
| キー | 操作内容 |
|---|---|
/ | フィードの一時停止 / 再開(読み取り用に凍結) |
/ , / | 行を一時停止して詳細パネルを開く |
| フォジィフィルター: プロセス名、PID、信号、ソース、処理結果への文字検索(一致部分はハイライト) |
| フィルターを「中断されたシステムコール」に制限 ( / ) |
| シグナル選択画面: 全信号のオン/オフ切り替え(リアルタイム更新) |
| 1 レベル戻る(フィルタークリア、選択解除など) |
| 終了 |
表示内容の詳細解説
各行は独立したブロックです。送信者からターゲットへ、色分けされた「ワイヤー(信号名)」が流れます。
色の種類 (Severity)
| カテゴリ (Priority) | 信号一覧 (Examples) | 色 (Colour) |
|---|---|---|
| kill | | hot red (鮮やかな赤) |
| fatal (core-dumping) | , , , , , , , | red |
| terminating | , , , , ... | amber (オレンジ) |
| job control | , , , | yellow |
| continue | | green |
| user | , | cyan |
| real-time | | violet (紫) |
| housekeeping | , , ... | grey |
注釈欄の構成要素
- ソース:
,kill(2)
,tgkill
, タイマー, カーネル, 故障など。sigqueue - 中断状態: 待機中のシステムコールが切断された場合、
(または SA_RESTART による自動再起動↯ EINTR read
) が記録されます。↺ restarted read - 処理結果:
: ハンドラ実行(例:caught <時間>
)41µs
: デフォルト動作適用(終了など)default
: 無視⊘ ignored
: 致命的な状態☠
シグナルの詳細確認
フィードを一時停止し、
または ↑/↓
で詳細パネルを開くと、配送側の情報全体が表示されます。p
| キー | 値の例 | 意味 |
|---|---|---|
| | 信号名・番号・カテゴリ |
/ | | 送信元/宛先(tid) |
| , , | 発射メソッド・詳細コード・スコープ |
| | 状態:配信済 |
| | 処理結果: ハンドラ呼び出し、デフォルト動作、無視のいずれか |
| 中断検出: 待機中のシステムコールが切断されたか ( で再開されたか) | |
| ハンドラアドレス | |
| 実行時間: までの経過時間 | |
| フラグ一覧 ( など) | |
| | デリヴァリー時のブロックマスク () |
- handled: ハンドラが実行された場合 (
)、デフォルト動作 (caught
)、無視 (default
)。ignored - syscall EINTR: 処理結果にはありません。中断を検知するためのみ表示されます(例:
)。EINTR ← read - TARGET BLOCKS: カーネルの
から直接取得された情報です。task_struct
「何が致命的とみなされるか」 (What counts as fatal)
☠「致命傷カウンター」と☠「行バッジ」は、**意図的に厳格(保守的)**に設定されています。なぜなら、生成時点ではターゲットがハンドラを持っているかが分からないためです(例:
SIGTERM はクリーンシャットダウンや無視の可能性もあります)。
☠ を付与するのは明白なケースのみです:
の配信 —— キャッチも無視も不可能。常に致命傷。SIGKILL- カーネル由来のコアダンプ誘発信号 (
,SEGV
,BUS
,ABRT
,ILL
,FPE
,TRAP
,SYS
) —— シンクロな故障またはキル。QUIT
それ以外のすべて(
systemd からの SIGTERM, キーボードの Ctrl-C の SIGINT, ランタイムからの自己管理信号など)は表示・色付けされますが、致命傷とはカウントされません。
シグナル選択器 (ライブカーネルノブ)
以下の 3 つの信号はホスト上で頻繁に発生する「雑音」となります:
(子プロセスのリピーク)SIGCHLD
(Go のハートビート)SIGURG
(ターミナルリサイズ)SIGWINCH
デフォルト設定: これら 3 つはカーネルレベルでミュートされており、フィードは重要度のあるトラフィックのみを表示します。
ミュートの切り替え
s キーを押し、シグナル選択器を開くと以下の操作が可能です:
- モーダルリストで全信号のオン/オフ切り替え。
- 矢印キーまたは数字入力で移動し、Space で瞬時のトグル。
キー: すべてを反転(ミュート解除 / ミュート)。a
仕組み:
- ミュートマスクは BPF プログラム内のグローバル変数に格納されており、行のトグル操作によって即時反映されます(再コンパイル不要)。
- カーネルはミュートされた信号をリングバッファに入れる前にドロップするため、オーバーヘッドはありません。
仕組み (How it works)
アーキテクチャ
コアは以下のコンポーネントで構成されています:
- BPF 側:
+src/bpf/sigwire.bpf.c
(カーネル空間)src/bpf/deliver.bpf.c - ユーザースペース:
src/probes/sigwire.js
すべてのイベントは
(target tid, signal) で相関付けられています。
BPF のトレースポイント
| プログラム | 付着先 (Probe) | 捕捉内容 |
|---|---|---|
| | 送信情報: 発射元、ターゲット、信号種別、グループフラグ。 ※ミュート設定があればここでドロップされる |
| | 配送情報: ディスポジション ()、フラグ、ブロック済み sigset。※ハンドラ実行用のスタンプ記録 |
| | 完了検出: 配信と戻り処理の差分からハンドラ走行時間を取得 |
| | 中断検出: の復帰を記録し、次回の配送と相関させて EINTR/再起動を判定 |
メモリマップ(共有領域)
- events: RINGBUF。生成イベント格納用。
- dispatch: RINGBUF。配送完了イベント格納用。
- mute_mask:
セクションのグローバル変数 (.data
)。ミュートビットマスク。__u64 - handler_start / restart_pending: 各スレッド (tid) 用の HASH マップ。時間窓内でイベントを相関付けるために使用。
JS のコンポーネント
| ファイル | 役割 |
|---|---|
| BPF オブジェクトのロード、マップバインド、自動付着 |
| 中核モジュール: 2 つのリングバッファ統合、相関ロジック、ミュート制御 |
| アプリのルート(入力、レイアウト、マウント) |
| メインボード: 「送信──SIG──▶ターゲット」フロー、結果表示、バッジ付け、色付け |
| サイドレール:トップ信号、ソース内訳、配送合計 |
| インスペクター:詳細情報の表示・操作 |
| シグナル選択モーダル |
| ヘッダー:ブランド、レート、合計、致命傷カウンター、ミュート数、停止状態 |
| フッター:キーヒントとフィルター案内 |
| データ定義: 名前、優先度、色、コードからメタデータをマッピング |
| フォーマッタ:パディング、トリミング、相対時刻計算、カウント統合 |
| 検索エンジン: 名/PID/信号/ソースへの部分文字列マッチ |
なぜ strace
や ptrace
の代わりにトレースポイントなのか?
straceptrace
: プロセスツリー単位で追跡するため、設定が複雑。イベント発生時停止が必要。strace -f
: 侵襲的であり、ターゲットごとに手動でのセットアップが必要。ptrace
(トレースポイント):sigwire- カーネルの「縫い目」を監視するだけであり、アプリ側の設定やプロセス停止は不要。
という全ライフサイクルを一度に捉え、送信者・ターゲットペア、処理結果、ハンドラ遅延、EINTR を包括的に可視化できる。生成 ↔ 配送 ↔ 完了
コミュニティからの疑問への回答
Q: 追跡されたプロセスへのオーバーヘッドはあるか? A: **ありません。**トレースポイントは受動的です。コストは各信号あたりのリングバッファ書き込みと EINTR 検出時の数命令のみです。ユーザースペースが処理しきれない場合、リングバッファーはドロップするだけでブロッキングしません。
Q: 既に動作中のプロセスの信号も表示されますか? A: はい。
sigwire がロードされた時点以降に発生するすべての信号をキャプチャします。過去のイベントは映らない特異性はありません。
Q: 特定の PID のみ追跡できますか? A: ホスト上の全プロセスを同時に監視・区分けしています。これはマシンの全体信号トラフィックです(単一 PID 限定ではありません)。
Q: データのエクスポートは可能ですか? A: 標準機能としてはいませんが、
src/probes/sigwire.js の RingBuf.subscribe を利用して、JSON/HTTP/Kafka へのストリーム出力をカスタマイズすることは可能です。
ソースからのビルド
以下のコマンドでローカル開発環境を構築します。システム側の C/BPF ツールチェーンや Node.js は不要です(依存はすべて vendored)。
make # 全ビルド (BPF + JS) make bpf # BPF オブジェクトのみ (`bin/probe.bpf.o`) make bundle # JS バンドルのみ (`src/index.jsx`) make clean # アーティファクト削除
ビルド後、以下のコマンドで実行します:
yeet run . # ローカルビルドの実行
ライセンス: Dual BSD/GPL。