在GNU-Prolog中,我能"抓住"linux信号吗?

Bam*_*bam 20 linux prolog gnu-prolog

有没有办法在GNU Prolog中"陷阱"(例如"捕获")操作系统信号?(我正在使用Ubuntu/Linux,最新的gprolog).

我想很久以前我在WAMCC中使用过这种方法,然后才变成GNU Prolog:

:- catch(Long_Running_Goal,signal(2),write('program interrupted'))
Run Code Online (Sandbox Code Playgroud)

但是,如果我使用(重复,失败)无限循环测试它,例如

:- catch((repeat,fail),X,write(X)).
Run Code Online (Sandbox Code Playgroud)

在解释按Ctrl-C还带我去跟踪/调试器,编译后的程序只是退出,如果我打断它kill -1,kill -2等等.

我已经尝试编译程序,--no-top-level以防默认顶层以某种方式捕获信号,但这没有任何区别.

SWI-Prolog似乎有一个合适的内置谓词on_signal,但是我正在寻找gprolog的解决方案,如果可能的话.

ffe*_*rri 10

在细算电流gprolog源代码,其中signal()使用:

  • SRC/BipsPl/os_interf_c.c: signal(SIGPIPE, SIG_IGN);
  • SRC/EnginePl/LINUX_SIGSEGV.c: signal(SIGSEGV, (void (*)()) SIGSEGV_Handler);
  • SRC/EnginePl/PPC_SIGSEGV.c: signal(SIGSEGV, (void (*)()) SIGSEGV_Handler);
  • SRC/EnginePl/SOLARIS_SIGSEGV.c: signal(SIGSEGV, (void (*)()) SIGSEGV_Handler);
  • SRC/EnginePl/stacks_sigsegv.c: signal(SIGSEGV, (void (*)(int)) SIGSEGV_Handler);
  • SRC/EnginePl/WIN32_all_SIGSEGV.c: signal(SIGSEGV, (void (*)(int)) SIGSEGV_Handler);
  • SRC/Linedit/ctrl_c.c: signal(sig, Wrapper_Handler);
  • SRC/Linedit/ctrl_c.c: signal(SIGINT, Wrapper_Handler);

我们可以看到信号的唯一用途是:

  • 在REPL中处理SIGINT(通过按CTRL+ 生成C)
  • 处理 SIGSEGV
  • 无视 SIGPIPE

所以这是不可能的,除非你愿意修改源代码.

另外,我在git commit消息中找不到任何信号.


Bam*_*bam 10

感谢mescalinum确认在GNU Prolog中默认无法使用信号处理.

但是GNU Prolog对C语言中的用户例程有很好的支持,我已经能够编写少量的C代码来捕获Linux信号并触发(如果需要)一个Prolog异常(注意我的是Ubuntu 14.04/GNU Prolog 1.3) .0因此init_signal函数的C类型Bool来自gprolog.h - 这在gprolog.h 1.3.1以后改为PlBool- 参见1.3.0最新手册相比):

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 */
}
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

编译 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$
Run Code Online (Sandbox Code Playgroud)

出于我的目的,我可以在C信号处理程序中有用地处理传入的异常,但是将它反映回Prolog'throw'(在这种情况下带有'实例化错误')将代码整齐地保存在Prolog中.

我希望能够向执行的GNU Prolog进程发送(和捕获)信号的原因是因为我的系统是一个高性能的并行处理Prolog环境,它可以触发任何长期运行的Prolog进程,以动态地将自己"拆分"为然后在其他机器上执行的多个部件.但是你从根本上不能(用我的方法)预测工作的确切分布,并且在适当的时候,其他处理器将被中断(即发送信号)以进一步分解工作量.

  • 大声笑这是一个持久的数字档案,旨在保护数据500年...不太有希望,但我想他们今天早上会把它唤醒. - [替代链接](http://people.ds.cam.ac.uk/ijl20/computer_science/prologpf/phd_dissertation.pdf) (2认同)