有没有办法陷入困境? (例如' catch')GNU Prolog中的操作系统信号? (我使用的是Ubuntu / Linux,最新的gprolog)。
我想很久以前我在WAMCC中使用过这种方法,然后才变成GNU Prolog:
:- catch(Long_Running_Goal,signal(2),write('program interrupted'))
但是,如果我使用(重复,失败)无限循环测试它,例如
:- catch((repeat,fail),X,write(X)).
在解释器中,Ctrl-C仍然会将我带到跟踪/调试器,如果我用kill -1
,kill -2
等中断它,编译后的程序就会退出。
我尝试使用--no-top-level
编译程序,以防默认顶层以某种方式捕获信号,但这没有任何区别。
SWI-Prolog似乎有一个合适的内置谓词on_signal
,它可以达到目的,但如果可能的话,我正在寻找gprolog的解决方案。
答案 0 :(得分:10)
查看使用current gprolog source code的signal()
后:
signal(SIGPIPE, SIG_IGN);
signal(SIGSEGV, (void (*)()) SIGSEGV_Handler);
signal(SIGSEGV, (void (*)()) SIGSEGV_Handler);
signal(SIGSEGV, (void (*)()) SIGSEGV_Handler);
signal(SIGSEGV, (void (*)(int)) SIGSEGV_Handler);
signal(SIGSEGV, (void (*)(int)) SIGSEGV_Handler);
signal(sig, Wrapper_Handler);
signal(SIGINT, Wrapper_Handler);
我们可以看到信号的唯一用途是:
SIGINT
(通过按 CTRL + C 生成)SIGSEGV
SIGPIPE
所以这是不可能的,除非你愿意修改源代码。
另外,我在git commit消息中找不到any mention of signals。
答案 1 :(得分:10)
感谢mescalinum确认signal handling is not available by default in GNU Prolog。
但是GNU Prolog对C语言中的用户例程提供了很好的支持,我已经能够编写少量的C代码来捕获Linux信号并触发(如果需要)一个Prolog异常(注意我的是Ubuntu) 14.04 / GNU Prolog 1.3.0所以init_signal
函数的C类型是来自gprolog.h的Bool
- 这在gprolog.h 1.3.1中已经改为PlBool
- 见{{3} } vs 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 */
}
在Prolog&#34; test.pl&#34;中测试用法 - &#34;长期运行&#34;此示例中的查询是o_query,用于&#39; catch&#39;关系,可以用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&#39; throw&#39; (在这种情况下带有&#39;实例化错误&#39;)将代码整齐地保存在Prolog中。
我希望能够向执行的GNU Prolog进程发送(和捕获)信号的原因是因为我的系统是一个高性能的并行处理Prolog环境,可以触发任何长期运行的Prolog进程动态# 39;分流&#39;它本身分成多个部分,然后在其他机器上执行。但是你从根本上不能(用我的方法)预测工作的确切分布,并且在适当的时候其他处理器将被中断(即发送信号)以进一步分解工作量。