🦕

DenoのaddSignalListenerではSIGKILLを受けることができない

2022/01/14に公開
Deno.addSignalListener("SIGKILL", () => console.log("Shutting down."));

と書いたところ

error: Uncaught (in promise) TypeError: Binding to signal 'SIGKILL' is not allowed
略
    at Object.opSync (deno:core/01_core.js:149:12)
    at bindSignal (deno:runtime/js/40_signals.js:13:17)
    at Object.addSignalListener (deno:runtime/js/40_signals.js:53:21)

と出ました。

なぜ?

エラーのスタックトレースを追うと、Rust側に処理をぶん投げているところにぶち当たりました。
https://github.com/denoland/deno/blob/main/runtime/js/40_signals.js#L12-L14
(ソースコードのURLを貼ったらいい感じに展開してほしいなぁできるようになっててすごい)

Rust側のコードはこんな感じです。
まさにここですね。

if signal_hook_registry::FORBIDDEN.contains(&signo) {
  return Err(type_error(format!(
    "Binding to signal '{}' is not allowed",
    sig
  )));
}

https://github.com/denoland/deno/blob/main/runtime/ops/signal.rs#L184-L189
(バージョンアップでソースコードの場所が変わっていて、表示がぶっ壊れています)

つまり、 SIGKILL は signal_hook_registry というライブラリで、禁断とされているシグナルに当たってしまっているようです。

実際のライブラリのコードもこのように記述がありました。

const FORBIDDEN_IMPL: &[c_int] = &[SIGKILL, SIGSTOP, SIGILL, SIGFPE, SIGSEGV];

https://github.com/vorner/signal-hook/blob/master/signal-hook-registry/src/lib.rs#L392

なるほど。
シンプルに知らなかったのですが、SIGKILLはそもそもキャッチできないんですね。勉強になりました。

まとめ

SIGKILLをプログラムでハンドリングするのはやめよう

以上です。よろしくお願いいたします。

Discussion