在 GNU-Prolog 中,我可以 'catch' 一个 linux 信号吗?
In GNU-Prolog, can I 'catch' a linux signal?
有没有办法在 GNU Prolog 中 'trap'(例如 'catch')操作系统信号? (我正在使用 Ubuntu/Linux,最新的 gprolog)。
我想很久以前我在 WAMCC 中使用过这种方法,然后才演变成 GNU Prolog:
:- catch(Long_Running_Goal,signal(2),write('program interrupted'))
但是如果我使用(重复,失败)无限循环来测试它,例如
:- catch((repeat,fail),X,write(X)).
在解释器中,Ctrl-C 仍然会带我到 trace/debugger,如果我用 kill -1
、kill -2
等中断它,编译的程序就会退出
我尝试用 --no-top-level
编译程序,以防默认顶层以某种方式捕获信号,但这没有任何区别。
SWI-Prolog 似乎有一个合适的内置谓词 on_signal
可以达到目的,但如果可能的话,我正在寻找 gprolog 的解决方案。
看了current gprolog source code where 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 提交消息中找不到 any mention of signals。
感谢mescalinum who confirmed 。
但是 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
- 请参阅 1.3.0 vs most recent 手册):
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" 中测试用法 - 本例中的 "long-running" 查询是 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 'throw'(在本例中使用 'instantiation error')将代码整齐地保存在 Prolog 中。
我希望能够向正在执行的 GNU Prolog 进程发送(并捕获)信号的原因是因为我的系统是一个高性能并行处理 Prolog 环境,它可以触发任何长-运行 ning Prolog 进程动态地将自身 'split' 分成多个部分,然后在其他机器上执行。但是你根本无法(用我的方法)预测工作的确切分配,并且在适当的时候其他处理器将被中断(即发送信号)以进一步分配工作量。
有没有办法在 GNU Prolog 中 'trap'(例如 'catch')操作系统信号? (我正在使用 Ubuntu/Linux,最新的 gprolog)。
我想很久以前我在 WAMCC 中使用过这种方法,然后才演变成 GNU Prolog:
:- catch(Long_Running_Goal,signal(2),write('program interrupted'))
但是如果我使用(重复,失败)无限循环来测试它,例如
:- catch((repeat,fail),X,write(X)).
在解释器中,Ctrl-C 仍然会带我到 trace/debugger,如果我用 kill -1
、kill -2
等中断它,编译的程序就会退出
我尝试用 --no-top-level
编译程序,以防默认顶层以某种方式捕获信号,但这没有任何区别。
SWI-Prolog 似乎有一个合适的内置谓词 on_signal
可以达到目的,但如果可能的话,我正在寻找 gprolog 的解决方案。
看了current gprolog source code where 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 中处理
- 处理
SIGSEGV
- 忽略
SIGPIPE
SIGINT
(通过按CTRL+C生成)
所以这是不可能的,除非你愿意修改源代码。
此外,我在 git 提交消息中找不到 any mention of signals。
感谢mescalinum who confirmed
但是 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
- 请参阅 1.3.0 vs most recent 手册):
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" 中测试用法 - 本例中的 "long-running" 查询是 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 'throw'(在本例中使用 'instantiation error')将代码整齐地保存在 Prolog 中。
我希望能够向正在执行的 GNU Prolog 进程发送(并捕获)信号的原因是因为我的系统是一个高性能并行处理 Prolog 环境,它可以触发任何长-运行 ning Prolog 进程动态地将自身 'split' 分成多个部分,然后在其他机器上执行。但是你根本无法(用我的方法)预测工作的确切分配,并且在适当的时候其他处理器将被中断(即发送信号)以进一步分配工作量。