🦕

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

1 min read
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側に処理をぶん投げているところにぶち当たりました。

function bindSignal(signo) {
  return core.opSync("op_signal_bind", signo);
}

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

ログインするとコメントできます