プロセスセンチネルとは、プロセスを終了、停止、または継続させるシグナル(Emacsによって送信されたものか、プロセス自身の動作によって生じたものかを問わない)を含む、いかなる理由であれ関連プロセスの状態が変化した際に呼び出される関数のことです。また、プロセスが終了した場合にもプロセスセンチネルは呼び出されます。センチネルには、イベントが発生したプロセスと、イベントの種類を示す文字列の2つの引数が渡されます。
プロセスにセンチネル関数が指定されていない場合は、デフォルトのセンチネル関数が使用されます。この関数は、プロセス名とイベントを説明する文字列を含むメッセージをプロセスのバッファに挿入します。
イベントを記述する文字列は、以下のいずれかの形式となります(ただし、これがイベント文字列のすべてを網羅しているわけではありません)。
"finished\n".
"deleted\n".
"exited abnormally with code exitcode (core dumped)\n". 「core
dumped」の部分は任意であり、プロセスがコアダンプした場合にのみ表示されます。
"failed with code fail-code\n".
"signal-description (core
dumped)\n". signal-description
はシグナルに関するシステム依存のテキスト記述です(例:SIGKILL に対する "killed")。「core
dumped」の部分は任意であり、プロセスがコアダンプした場合にのみ表示されます。
"open from host-name\n".
"open\n".
"run\n".
"connection broken by remote peer\n".
センチネルは、Emacsが待機している間(例えば、ターミナルからの入力、一定時間の経過、またはプロセスからの出力を待っている間)のみ実行されます。これにより、他のLispプログラムの途中で任意の箇所でセンチネルを実行した際に生じうるタイミングエラーを回避できます。プログラムは、sit-for や sleep-for(経過時間または入力の待機を参照)、あるいは accept-process-output(プロセスからの出力の受理を参照)を呼び出すことで待機し、センチネルを実行させることができます。また、Emacsではコマンドループが入力を読み込んでいる間もセンチネルを実行させることができます。delete-process は、実行中のプロセスを終了させる際にセンチネルを呼び出します。
Emacsは、1つのプロセスのセンチネルを呼び出すための複数の理由をキューに保持しません。現在のステータスと、変更があったという事実のみを記録します。そのため、ステータスの変更が立て続けに2回発生しても、センチネルが呼び出されるのは1回のみとなります。ただし、プロセスの終了時には、必ずちょうど1回だけセンチネルが実行されます。これは、終了後はプロセスのステータスが再度変化することはないためです。
Emacsは、プロセスセンチネルを実行する前に、プロセスからの出力の有無を明示的に確認します。プロセスの終了によりセンチネルが実行されると、それ以降、プロセスから出力が届くことはありません。
プロセスのバッファに出力を書き込むセンティネルは、バッファがまだ有効であるかを確認すべきである。デッドバッファに挿入しようとした場合、エラーが発生する。バッファがデッドである場合、(buffer-name (process-buffer process))はnilを返す。
通常、センチネル内での終了は抑制されています。そうしないと、コマンドレベルで C-g
と入力したり、ユーザーコマンドを終了させたりした際の挙動が予測不能になるためです。センチネル内での終了を許可したい場合は、inhibit-quit を nil
にバインドしてください。多くの場合、これを実現する適切な方法はマクロ with-local-quit
を使用することです。終了 を参照してください。
センチネルの実行中にエラーが発生した場合、それは自動的に捕捉されるため、センチネルの起動時に実行されていたプログラムの動作が停止することはありません。ただし、debug-on-error が nil
以外の場合、エラーは捕捉されません。これにより、Lispデバッガを使用してセンチネルをデバッグすることが可能になります。Lispデバッガを参照してください。エラーが捕捉されると、ユーザーがエラーを確認できるよう、Emacsは
process-error-pause-time 秒間一時停止します。非同期プロセスの作成を参照してください。
センチネルが実行されている間は、センチネルが再帰的に実行されないよう、プロセスセンチネルが一時的に nil に設定されます。このため、センチネルが新しいセンチネルを指定することはできません。
なお、Emacsはセンチネルの実行中に、マッチデータを自動的に保存・復元します。マッチデータを参照してください。
この関数は sentinel を process
に関連付けます。sentinel が nil
である場合、プロセスはデフォルトのセンチネルを持ち、プロセスのステータスが変更された際にメッセージがプロセスのバッファに挿入されます。
プロセスセンチネルの変更は即座に反映されます。センチネルの実行が予定されているもののまだ呼び出されていない状態で新しいセンチネルを指定した場合、最終的にそのセンチネルが呼び出される際には、新しいセンチネルが使用されます。
(defun msg-me (process event)
(princ
(format "Process: %s had the event '%s'" process event)))
(set-process-sentinel (get-process "shell") 'msg-me)
⇒ msg-me
(kill-process (get-process "shell"))
⊣ Process: #<process shell> had the event 'killed'
⇒ #<process shell>
この関数は process のセンチネルを返します。
プロセスの状態変化を複数のセンチネルに伝える必要がある場合は、add-function
を使用して既存のセンチネルと新しいセンチネルを結合できます。Advising Emacs Lisp Functions を参照してください。
センチネル関数またはフィルタ関数が実行されている間、この関数は、センチネル関数またはフィルタ関数が呼び出された時点でEmacsがユーザーからのキーボード入力を待機していた場合は非nilを、そうでなければnilを返します。