プロセスセンチネル(process sentinel: プロセス番兵)とは、(Emacsにより送信されたか、そのプロセス自身の動作が原因で送信された)プロセスを終了、停止、継続するシグナルを含む、何らかの理由により関連付けられたプロセスの状態が変化した際には常に呼び出される関数のことです。プロセスがexitする際にもプロセスセンチネルが呼び出されます。センチネルはイベントが発生したプロセスとイベントのタイプを記述する文字列という2つの引数を受け取ります。
プロセスにたいして何もセンチネル関数が指定されていなければ、プロセスのバッファーにプロセス名とイベントを記述する文字列とともにメッセージを挿入するデフォルトのセンチネル関数を使用します。
イベントを記述する文字列は以下のいずれかのような外見をもちます(ただしイベント文字列を網羅したリストではない):
"finished\n"
.
"deleted\n"
.
"exited abnormally with code exitcode (core dumped)\n"
."failed with code fail-code\n"
.
"signal-description (core
dumped)\n"
.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回センチネルを実行するでしょう。これは終了後にプロセス状態が再び変更されることはないからです。
Emacsはプロセスセンチネル実行の前にプロセスからの出力をチェックします。プロセス終了によりセンチネルが一度実行されると、そのプロセスから更なる出力は到着しません。
プロセスのバッファーに出力を書き込むセンチネルは、そのバッファーがまだ生きているかチェックするべきです。死んだバッファーへの挿入を試みるとエラーになるでしょう。そのバッファーがすでに死んでいれば(buffer-name
(process-buffer process))
はnil
をリターンします。
quitは通常はセンチネル内では抑制されます。さもないとコマンドレベルでのC-gのタイプ、またはユーザーコマンドのquitは予測できません。センチネル内部でのquitを許可したければinhibit-quit
をnil
にバインドしてください。ほとんどの場合において、これを行う正しい方法はマクロwith-local-quit
です。quitを参照してください。
センチネルの実行中にエラーが発生した場合には、センチネル開始時に実行中だったプログラムが何であれ実行を停止しないように自動的にcatchされます。しかしdebug-on-error
が非nil
ならエラーはcatchされません。これによりLispデバッガーを使用したセンチネルのデバッグが可能になります。Lispデバッガを参照してください。エラーがcatchされると、ユーザーがそのエラーを確認できるように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
を使用できます。Emacs Lisp関数にたいするアドバイスを参照してください。
この関数はセンチネルやフィルター関数の実行中に、もしEmacsがセンチネルやフィルター関数呼び出し時にユーザーのキーボード入力を待機していたら非nil
、そうでなければnil
をリターンする。