# 7.1 `signal` -- 非同期イベントにハンドラを設定する

このモジュールでは Python でシグナルハンドラを使うための機構を 提供します。シグナルとハンドラを扱う上では、一般的なルールが いくつかあります:

- 特定のシグナルに対するハンドラが一度設定されると、明示的に リセットしないかぎり設定されたままになります (Python は背後の実装系 に関係なく BSD 形式のインタフェースをエミュレートします)。 例外は `SIGCHLD` のハンドラで、この場合は背後の実装系の 仕様に従います。

- クリティカルセクションから一時的にシグナルを``ブロック''することは できません。この機能をサポートしないUnix系システムも存在するた めです。

- Python のシグナルハンドラは Python のユーザが望む限り非同期で呼び 出されますが、呼び出されるのは Python インタプリタの ``原子的な (atomic)'' 命令実行単位の間です。従って、 (巨大なサイズのテキストに対する正規表現の一致検索のような) 純粋に C 言語のレベルで実現されている時間のかかる処理中に 到着したシグナルは、不定期間遅延する可能性があります。

- シグナルが I/O 操作中に到着すると、シグナルハンドラが処理を返した 後に I/O 操作が例外を送出する可能性があります。 これは背後にある Unix システムが割り込みシステムコールにどういう 意味付けをしているかに依存します。

- C 言語のシグナルハンドラは常に処理を返すので、`SIGFPE` や `SIGSEGV` のような同期エラーの捕捉はほとんど意味が ありません。

- Python は標準でごく小数のシグナルハンドラをインストールしています: `SIGPIPE` は無視されます (従って、パイプやソケットに対する 書き込みで生じたエラーは通常の Python 例外として報告されます) `SIGINT` は `KeyboardInterrupt` 例外に変換されます。 これらはどれも上書きすることができます。

- シグナルとスレッドの両方を同じプログラムで使用する場合にはいくつか 注意が必要です。シグナルとスレッドを同時に利用する上で基本的に注意 すべきことは: 常に `signal()` 命令は主スレッド (main thread)の 処理中で実行するということです。どのスレッドも `alarm()`、 `getsignal()`、あるいは `pause()` を実行する ことができます; しかし、主スレッドだけが新たなシグナルハンドラを 設定することができ、従ってシグナルを受け取ることができるのは主スレッド だけです (これは、背後のスレッド実装が個々のスレッドに対するシグナル 送信をサポートしているかに関わらず、Python `signal` モジュール が強制している仕様です)。従って、シグナルをスレッド間通信の手段として 使うことはできません。代わりにロック機構を使ってください。

以下に `signal` モジュールで定義されている変数を示します:

`SIG_DFL`
  二つある標準シグナル処理オプションのうちの一つです; 単にシグナルに 対する標準の関数を実行します。例えば、ほとんどのシステムでは、 `SIGQUIT` に対する標準の動作はコアダンプと終了で、 `SIGCLD` に対する標準の動作は単にシグナルの無視です。

`SIG_IGN`
  もう一つの標準シグナル処理オプションで、単に受け取ったシグナルを 無視します。

`SIG*`
  全てのシグナル番号はシンボル定義されています。例えば、ハングアップ シグナルは `signal.SIGHUP` で定義されています; 変数名は C 言語のプログラムで使われているのと同じ名前で、`<signal.h>` にあります。 ``signal()`' に関する Unix マニュアルページでは、 システムで定義されているシグナルを列挙しています (あるシステムではリストは signal(2) に、別のシステムでは signal(7) に列挙されています)。 全てのシステムで同じシグナル名のセットを定義しているわけではないので 注意してください; このモジュールでは、システムで定義されているシグナル 名だけを定義しています。

`NSIG`
  最も大きいシグナル番号に 1 を足した値です。

`signal` モジュールでは以下の関数を定義しています:

`alarm`( | time)

  time がゼロでない値の場合、この関数は time 秒後頃に `SIGALRM` をプロセスに送るように要求します。 それ以前にスケジュールしたアラームはキャンセルされます (常に一つの アラームしかスケジュールできません)。この場合、戻り値は以前に設定 されたアラームシグナルが通知されるまであと何秒だったかを示す値です。 time がゼロの場合、アラームは一切スケジュールされず、現在 スケジュールされているアラームがキャンセルされます。 戻り値は以前にスケジュールされたアラームが通知される予定時刻までの 残り時間です。戻り値がゼロの場合、現在アラームがスケジュールされて いないことを示します。(Unix マニュアルページ alarm(2) を参照してください)。 利用可能: Unix。

`getsignal`( | signalnum)

  シグナル signalnum に対する現在のシグナルハンドラを返します。 戻り値は呼び出し可能な Python オブジェクトか、`signal.SIG_IGN`、 `signal.SIG_DFL`、および `None` といった特殊な値 のいずれかです。ここで `signal.SIG_IGN` は以前そのシグナルが 無視されていたことを示し、`signal.SIG_DFL` は以前そのシグナルの 標準の処理方法が使われていたことを示し、`None` はシグナルハンドラが まだ Python によってインストールされていないことを示します。

`pause`( | )

  シグナルを受け取るまでプロセスを一時停止します; その後、適切な ハンドラが呼び出されます。戻り値はありません。Windows では利用 できません。(Unix マニュアルページ signal(2) を 参照してください。)

`signal`( | signalnum, handler)

  シグナル signalnum に対するハンドラを関数 handler にします。 handler は二つの引数 (下記参照) を取る呼び出し可能な Python オブジェクトにするか、`signal.SIG_IGN` あるいは `signal.SIG_DFL` といった特殊な値にすることができます。 以前に使われていたシグナルハンドラが返されます (上記の `getsignal()` の記述を参照してください)。 (Unix マニュアルページ signal(2) を参照してください。)

  複数スレッドの使用が有効な場合、この関数は主スレッドからのみ呼び出す ことができます; 主スレッド以外のスレッドで呼び出そうとすると、例外 `ValueError` が送出されます。

  handler は二つの引数: シグナル番号、および現在のスタックフレーム (`None` またはフレームオブジェクト; フレームオブジェクトに ついての記述はリファレンスマニュアルを参照してください)、 とともに呼び出されます。