GNU Prolog ではデフォルトでシグナル処理が利用できないことを確認してくれたmescalinumに感謝します。
しかし、GNU Prolog は C でのユーザー ルーチンの優れたサポートを備えており、Linux シグナルをキャッチして (必要に応じて) Prolog 例外をトリガーする少量の C コードを書くことができました (私の場合は Ubuntu 14.04/GNU Prolog 1.3 であることに注意してください)。 .0 したがって、init_signal
関数の C タイプはBool
gprolog.h からのものです - これは gprolog.h 1.3.1 以降で変更されました- 1.3.0と最新のマニュアルPlBool
を参照してください):
C コード "signal.c":
#include <stdio.h>
#include <signal.h>
#include <gprolog.h>
/* signal handler */
void sig_handler(int signo)
{
if (signo == SIGHUP)
{
printf("received SIGHUP\n");
/* throw Prolog exception */
Pl_Err_Instantiation();
}
}
/* GNU Prolog goal that registers the signal handler */
/* declared with :- foreign(init_signal). */
Bool init_signal()
{
if (signal(SIGHUP, sig_handler) == SIG_ERR)
{
printf("\ncan't catch SIGHUP\n");
}
printf("%s","SIGHUP handler registered\n");
return TRUE; /* succeed */
}
Prolog "test.pl" での使用方法のテスト - この例の "長時間実行" クエリは o_query であり、'catch' リレーションで使用され、SIGHUP で中断できます。
:- foreign(init_signal).
:- initialization(main).
main :- write('Prolog signal test program started'),
nl,
init_signal,
catch(o_query,X,write('Prolog exception thrown')),
nl,
halt.
o_query :- repeat,
sleep(1),
fail.
でコンパイルgplc test.pl signal.c
プログラムが ./test で実行されている場合、別の端末から中断することができますkill -1 <test process id>
Bambam@desktop:~/prolog/signal$ ./test
Prolog signal test program started
SIGHUP handler registered
received SIGHUP
Prolog exception thrown
Bambam@desktop:~/prolog/signal$
私の目的では、C シグナル ハンドラーにいる間に入ってくる例外を便利に処理できますが、それを Prolog の「スロー」(この場合は「インスタンス化エラー」) に反映することで、コードを Prolog 内にきちんと保持します。
実行中の GNU Prolog プロセスにシグナルを送信 (およびキャッチ) できるようにしたい理由は、私のシステムが高性能の並列処理 Prolog 環境であるためです。複数のパーツが他のマシンで実行されます。しかし、基本的に (私の方法では) 作業の正確な分散を予測することはできず、やがて他のプロセッサが中断され (つまり、信号が送信され)、ワークロードがさらに分割されます。