21

GNU Prolog 内でオペレーティング システムのシグナルを「トラップ」(たとえば「キャッチ」) する方法はありますか? (Ubuntu/Linux、最新の gprolog を使用しています)。

GNU Prolog に変形する前に、私はずっと前に WAMCC でこのアプローチを使用したと思います。

:- catch(Long_Running_Goal,signal(2),write('program interrupted'))

しかし、たとえば、(repeat,fail) 無限ループを使用してこれをテストすると、

:- catch((repeat,fail),X,write(X)).

インタプリタで Ctrl-C を押すと、まだトレース/デバッガに移動し、コンパイルされたプログラムは などで中断すると終了しkill -1ますkill -2

--no-top-levelデフォルトのトップレベルが何らかの形で信号をキャプチャする場合に備えて、プログラムをコンパイルしようとしましたが、違いはありませんでした。

SWI-Prolog にon_signalは目的を果たす適切な組み込みの述語があるようですが、可能であれば gprolog を使用した解決策を探しています。

4

2 に答える 2

11

GNU Prolog ではデフォルトでシグナル処理が利用できないことを確認してくれたmescalinumに感謝します。

しかし、GNU Prolog は C でのユーザー ルーチンの優れたサポートを備えており、Linux シグナルをキャッチして (必要に応じて) Prolog 例外をトリガーする少量の C コードを書くことができました (私の場合は Ubuntu 14.04/GNU Prolog 1.3 であることに注意してください)。 .0 したがって、init_signal関数の C タイプはBoolgprolog.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 環境であるためです。複数のパーツが他のマシンで実行されます。しかし、基本的に (私の方法では) 作業の正確な分散を予測することはできず、やがて他のプロセッサが中断され (つまり、信号が送信され)、ワークロードがさらに分割されます。

于 2015-06-29T08:30:08.897 に答える