2015-06-20 33 views
20

有没有办法在GNU Prolog中“捕捉”(例如'捕捉')操作系统信号? (我使用的是Ubuntu/Linux,最新的gprolog)。在GNU-Prolog中,我能“捕捉”一个linux信号吗?

我想很久以前我曾经在WAMCC这种方法,在此之前演变为GNU序言:

:- 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的解决方案。

+1

嗨 - 仍然希望对此有所帮助......但同时我可以评论说,这个需求的原因是一个并行处理实验方法,其中Prolog可执行文件可能被另一个进程中断,并且在那一点上如果咳嗽一个代表其当前搜索进度的“状态”值,以便可以将处理从该点分离并分配给其他处理器。在这方面有很多工作,但我的方法取决于这个中断能力,它在wamcc中有。 – Bambam

+1

@Bamb:听起来很像Condor。该州有多大?作为一个底线喂养员,我经常写出一个州。 – false

+0

我刚刚研究出'赏金'来自哪里......谢谢你。 – Bambam

回答

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所以C型为init_signal功能是从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”中的测试用法特等” - 在‘在这个例子中长时间运行的’查询o_query,在一个‘抓’的关系使用,并且可以用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>

[email protected]:~/prolog/signal$ ./test 
Prolog signal test program started 
SIGHUP handler registered 
received SIGHUP 
Prolog exception thrown 
[email protected]:~/prolog/signal$ 

对于我而言中断运行,我可以有效地处理传入的异常,而我在C信号处理程序来的,但反映了它回到一个序言“抛出'(在这种情况下是“瞬间” iation错误')将代码整齐地保存在Prolog中。

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

+0

GNU现在是1.4.4响应。 1.4.5 ... – false

+0

什么时候进程会分裂?这种情况发生的频率如何?根据我的经验,这是相当(可预见的)停机时间,这是大规模并行任务的一个问题。 – false

+0

“流程何时会分裂?这种情况发生的频率如何?” - [链接](https://www.repository.cam.ac.uk/handle/1810/221792) – Bambam

10

看着current gprolog source code其中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);

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

  • 处理SIGINT在REPL(按CTRL + Ç产生)
  • 处理SIGSEGV
  • 忽略SIGPIPE

所以这是不可能的,除非你愿意修改源代码。我在git commit消息中找不到any mention of signals

+1

谢谢mescalinum ...非常感谢。因为我真的*需要打断我编译的prolog程序。我的下一步将是看看我是否可以混合一些C来捕捉信号并触发一个Throw ... – Bambam