"signal" — 非同期イベントにハンドラを設定する
*********************************************

This module provides mechanisms to use signal handlers in Python. Some
general rules for working with signals and their handlers:

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

* There is no way to 「block」 signals temporarily from critical
  sections (since this is not supported by all Unix flavors).

* Although Python signal handlers are called asynchronously as far
  as the Python user is concerned, they can only occur between the 「
  atomic」 instructions of the Python interpreter.  This means that
  signals arriving during long calculations implemented purely in C
  (such as regular expression matches on large bodies of text) may be
  delayed for an arbitrary amount of time.

* When a signal arrives during an I/O operation, it is possible that
  the I/O operation raises an exception after the signal handler
  returns. This is dependent on the underlying Unix system’s semantics
  regarding interrupted system calls.

* Because the C signal handler always returns, it makes little sense
  to catch synchronous errors like "SIGFPE" or "SIGSEGV".

* Python installs a small number of signal handlers by default:
  "SIGPIPE" is ignored (so write errors on pipes and sockets can be
  reported as ordinary Python exceptions) and "SIGINT" is translated
  into a "KeyboardInterrupt" exception.  All of these can be
  overridden.

* Some care must be taken if both signals and threads are used in
  the same program.  The fundamental thing to remember in using
  signals and threads simultaneously is: always perform "signal()"
  operations in the main thread of execution.  Any thread can perform
  an "alarm()", "getsignal()", "pause()", "setitimer()" or
  "getitimer()"; only the main thread can set a new signal handler,
  and the main thread will be the only one to receive signals (this is
  enforced by the Python "signal" module, even if the underlying
  thread implementation supports sending signals to individual
  threads). This means that signals can’t be used as a means of inter-
  thread communication.  Use locks instead.

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

signal.SIG_DFL

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

signal.SIG_IGN

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

SIG*

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

signal.CTRL_C_EVENT

   "CTRL+C" キーストロークに該当するシグナル。このシグナルは
   "os.kill()" でだけ利用できます。

   利用できる環境 : Windows.

   バージョン 2.7 で追加.

signal.CTRL_BREAK_EVENT

   "CTRL+BREAK" キーストロークに該当するシグナル。このシグナルは
   "os.kill()" でだけ利用できます。

   利用できる環境 : Windows.

   バージョン 2.7 で追加.

signal.NSIG

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

signal.ITIMER_REAL

   実時間でデクリメントするインターバルタイマーです。タイマーが発火し
   たときに "SIGALRM" を送ります。

signal.ITIMER_VIRTUAL

   プロセスの実行時間だけデクリメントするインターバルタイマーです。タ
   イマーが発火したときに "SIGVTALRM" を送ります。

signal.ITIMER_PROF

   プロセスの実行中と、システムがそのプロセスのために実行している時間
   だけデクリメントするインターバルタイマーです。ITIMER_VIRTUAL と組み
   合わせて、このタイマーはよくアプリケーションがユーザー空間とカーネ
   ル空間で消費した時間のプロファイリングに利用されます。タイマーが発
   火したときに "SIGPROF" を送ります。

"signal" モジュールは1つの例外を定義しています:

exception signal.ItimerError

   Raised to signal an error from the underlying "setitimer()" or
   "getitimer()" implementation. Expect this error if an invalid
   interval timer or a negative time is passed to "setitimer()". This
   error is a subtype of "IOError".

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

signal.alarm(time)

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

signal.getsignal(signalnum)

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

signal.pause()

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

signal.setitimer(which, seconds[, interval])

   *which* で指定されたタイマー ("signal.ITIMER_REAL",
   "signal.ITIMER_VIRTUAL", "signal.ITIMER_PROF" のどれか) を、
   *seconds* 秒後と ("alarm()" と異なり、floatを指定できます)、それか
   ら *interval* 秒間隔で起動するように設定します。 *seconds* に0を指
   定すると、*which* で指定されたタイマーをクリアすることができます。

   インターバルタイマーが起動したとき、シグナルがプロセスに送られます
   。送られるシグナルは利用されたタイマーの種類に依存します。
   "signal.ITIMER_REAL" の場合は "SIGALRM" が、
   "signal.ITIMER_VIRTUAL" の場合は "SIGVTALRM" が、
   "signal.ITIMER_PROF" の場合は "SIGPROF" が送られます。

   以前の値が (delay, interval) のタプルとして返されます。

   無効なインターバルタイマーを渡すと "ItimerError" 例外が発生します。
   利用できる環境: Unix。

   バージョン 2.6 で追加.

signal.getitimer(which)

   *which* で指定されたインターバルタイマーの現在の値を返します。利用
   できる環境: Unix。

   バージョン 2.6 で追加.

signal.set_wakeup_fd(fd)

   Set the wakeup fd to *fd*.  When a signal is received, a "'\0'"
   byte is written to the fd.  This can be used by a library to wakeup
   a poll or select call, allowing the signal to be fully processed.

   The old wakeup fd is returned (or -1 if file descriptor wakeup was
   not enabled).  If *fd* is -1, file descriptor wakeup is disabled.
   If not -1, *fd* must be non-blocking.  It is up to the library to
   remove any bytes from *fd* before calling poll or select again.

   スレッドが有効な場合、この関数はメインスレッドからしか実行できませ
   ん。それ以外のスレッドからこの関数を実行しようとすると "ValueError"
   例外が発生します。

   バージョン 2.6 で追加.

signal.siginterrupt(signalnum, flag)

   システムコールのリスタートの動作を変更します。 *flag* が "False" の
   場合、 *signalnum* シグナルに中断されたシステムコールは再実行されま
   す。それ以外の場合、システムコールは中断されます。戻り値はありませ
   ん。利用できる環境: Unix (詳しい情報についてはマニュアルページ
   *siginterrupt(3)* を参照してください)。

   "signal()" を使ってシグナルハンドラを設定したときに、暗黙のうちに
   *flag* に true を指定して "siginterrupt()" が実行されるため、中断に
   対するリスタートの動作がリセットされることに注意してください。

   バージョン 2.6 で追加.

signal.signal(signalnum, handler)

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

   スレッドが有効な場合、この関数はメインスレッドからしか実行できませ
   ん。それ以外のスレッドからこの関数を実行しようとすると "ValueError"
   例外が発生します。

   *handler* は二つの引数とともに呼び出されます: シグナル番号、および
   現在のスタックフレーム ("None" またはフレームオブジェクト; フレーム
   オブジェクトについての記述は 標準型の階層における説明 か、
   "inspect" モジュールの属性の説明を参照してください)。

   On Windows, "signal()" can only be called with "SIGABRT", "SIGFPE",
   "SIGILL", "SIGINT", "SIGSEGV", or "SIGTERM". A "ValueError" will be
   raised in any other case.


使用例
======

以下は最小限のプログラム例です。この例では "alarm()" を使ってファイル
を開く処理を待つのに費やす時間を制限します; 例えば、電源の入っていない
シリアルデバイスを開こうとすると、通常 "os.open()" は未定義の期間ハン
グアップしてしまいますが、この方法はそうした場合に便利です。ここではフ
ァイルを開くまで 5 秒間のアラームを設定することで解決しています; ファ
イルを開く処理が長くかかりすぎると、アラームシグナルが送信され、ハンド
ラが例外を送出するようになっています。

   import signal, os

   def handler(signum, frame):
       print 'Signal handler called with signal', signum
       raise IOError("Couldn't open device!")

   # Set the signal handler and a 5-second alarm
   signal.signal(signal.SIGALRM, handler)
   signal.alarm(5)

   # This open() may hang indefinitely
   fd = os.open('/dev/ttyS0', os.O_RDWR)

   signal.alarm(0)          # Disable the alarm
