2015-06-20 11 views
20

Czy istnieje sposób na "pułapkę" (np. "Catch") sygnału systemu operacyjnego w GNU Prolog? (Używam Ubuntu/Linux, najnowszy gprolog).W GNU-Prolog, czy mogę "złapać" sygnał linux?

myślę dawno użyłem tego podejścia w WAMCC, przed który przekształcił GNU Prolog:

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

Ale jeśli to sprawdzić za pomocą (powtórki, fail) nieskończoną pętlę, na przykład

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

w tłumacza Ctrl-C nadal zabiera mnie do śledzenia/debugger, a skompilowany program właśnie kończy pracę, jeśli przerwać ją kill -1, kill -2 itp

Próbowałem skompilować program z --no-top-level na wypadek, gdyby sygnał domyślny przechwycił sygnał, ale to nie miało znaczenia.

SWI-Prolog wydaje się mieć odpowiedni wbudowany predykat on_signal który służy celowi, ale szukam rozwiązania z gprolog jeśli to możliwe.

+1

Witam - wciąż mam nadzieję na jakąś pomoc w tej sprawie ... ale w międzyczasie mogę powiedzieć, że powodem tego wymagania jest eksperymentalne podejście do przetwarzania równoległego, w którym plik wykonywalny Prolog może zostać przerwany przez inny proces iw tym momencie jeśli kaszle w górę wartość "stanu", która reprezentuje jej postęp w bieżącym wyszukiwaniu, tak że przetwarzanie może zostać podzielone z tego punktu i przypisane do innych procesorów. W tej dziedzinie jest dużo pracy, ale moje podejście zależy raczej od tej możliwości przerwań, która * była * w WEGCC. – Bambam

+1

@Bamb: brzmi bardzo podobnie do Condora. Jak duży jest ten stan? Jako dolny dostawca regularnie pisałem państwo. – false

+0

Właśnie dowiedziałem się, skąd pochodzi "nagroda" ... dzięki fałszywej. – Bambam

Odpowiedz

10

Dzięki mescalinum, który potwierdził signal handling is not available by default in GNU Prolog.

Ale GNU Prolog ma doskonałe wsparcie dla procedur użytkownika w C, i byłem w stanie napisać niewielką ilość kodu C, który przechwytuje sygnał Linuxa i uruchamia (w razie potrzeby) wyjątek Prolog (uwaga moja to Ubuntu 14.04/GNU Prologa 1.3.0 więc typu C init_signal funkcji jest Bool z gprolog.h - zmieniło w gprolog.h 1.3.1 dalej do PlBool - patrz 1.3.0 vs most recent instrukcje)

kodu 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 */ 
} 

Zastosowanie testu w Prologu "test .pl”- w«długotrwały»kwerendy w tym przykładzie jest o_query, wykorzystywane w«catch»relacji i może być przerwany z 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. 

skompilować z gplc test.pl signal.c

Teraz, jeśli program jest uruchomić z ./test może zostać przerwane z innego terminala z 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$ 

do moich celów, mogę z powodzeniem obsłużyć wyjątek przychodzące, gdy jestem w obsługi sygnału C, ale odzwierciedlające go z powrotem do Prologu " throw "(w tym przypadku z" instant " iation error ") utrzymuje porządek w kodzie Prolog.

Powodem, dla którego chcę być w stanie wysłać (i złapać) sygnał do wykonywanego procesu GNU Prolog, jest to, że mój system jest środowiskiem przetwarzania Prologu o wysokiej wydajności, które może dynamicznie uruchamiać każdy długotrwały proces Prologa. podzielić się na wiele części, które następnie można wykonać na innych maszynach. Ale zasadniczo nie możesz (z moją metodą) przewidzieć dokładnego podziału pracy, a we właściwym czasie inne procesory zostaną przerwane (tj. Wysłany sygnał) w celu dalszego podziału obciążenia.

+0

GNU jest teraz 1.4.4 lub. 1.4.5 ... – false

+0

Kiedy proces zostanie podzielony? Jak często to się dzieje? Z mojego doświadczenia wynika raczej (przewidywany) czas przestoju, który stanowi problem z masowo równoległymi zadaniami. – false

+0

"Kiedy nastąpi podział procesu? Jak często to się dzieje?" - [link] (https://www.repository.cam.ac.uk/handle/1810/221792) – Bambam

10

Po obejrzeniu current gprolog source code gdzie stosowany jest 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);

widzimy tylko wykorzystanie sygnałów jest:

  • obsłużyć SIGINT (generowane przez naciśnięcie CTRL + C) w REPL
  • obsłużyć SIGSEGV
  • ignorować SIGPIPE

Więc to nie jest możliwe, chyba że jesteś gotów zmodyfikować kod źródłowy.

Ponadto nie mogłem znaleźć any mention of signals w wiadomościach zatwierdzenia git.

+1

Dzięki mescalinum ... v bardzo docenione. Wstyd, ponieważ * naprawdę * muszę przerwać moje skompilowane programy prologów. Następnym krokiem będzie sprawdzenie, czy mogę połączyć się z C, aby złapać sygnał i wywołać Throw ... – Bambam

Powiązane problemy