2013-08-25 16 views
14

Jeśli naciśnie się Ctrl + C, spowoduje to wyjątek (zawsze w wątku 0?). Możesz go złapać, jeśli chcesz - lub, co bardziej prawdopodobne, przeprowadzić pewne porządki, a następnie ponownie je rzucić. Ale zwykle skutkuje to zatrzymaniem programu w taki czy inny sposób.Zabicie binarki Haskella

Załóżmy teraz, że używam polecenia Unix kill. Jak rozumiem, kill zasadniczo wysyła (konfigurowalny) sygnał Unix do określonego procesu.

Jak reaguje RTS Haskell? Czy gdzieś to dokumentuje? Chciałbym wyobrazić że wysyłanie SIGTERM miałoby ten sam efekt co naciśnięcie klawiszy Ctrl + C, ale nie wiem, że na pewno, że ...

(i, oczywiście, można użyć kill do wysyłania sygnałów, że nie mają nic wspólnego z zabijania w ogóle. Ponownie, chciałbym wyobrazić że RTS będzie ignorować, powiedzmy, SIGHUP lub SIGPWR, ale nie wiem na pewno.)

+3

Ctrl-C wysyła 'SIGINT'. Spodziewałbym się, że 'SIGTERM' będzie traktowany inaczej niż" SIGINT ". –

+2

Myślę, że istnieje domyślna akcja dla wszystkich sygnałów zdefiniowanych przez Posix i/lub konkretny system, patrz tutaj: http://man7.org/linux/man-pages/man7/signal.7.html (Przewiń w dół do stół). – bennofs

+1

@bennofs Warto wiedzieć. Domyślna akcja dla 'SIGINT' wydaje się zakończyć proces, ale RTS wyraźnie obsługuje to specjalnie. Byłoby miło wiedzieć, czy jakikolwiek inny sygnał jest traktowany w specjalny sposób ... – MathematicalOrchid

Odpowiedz

12

wyszukiwania dla „sygnału” w ghc source code na github ujawnił installDefaultSignals funkcję:

void 
initDefaultHandlers(void) 
{ 
    struct sigaction action,oact; 

    // install the SIGINT handler 
    action.sa_handler = shutdown_handler; 
    sigemptyset(&action.sa_mask); 
    action.sa_flags = 0; 
    if (sigaction(SIGINT, &action, &oact) != 0) { 
sysErrorBelch("warning: failed to install SIGINT handler"); 
    } 

#if defined(HAVE_SIGINTERRUPT) 
    siginterrupt(SIGINT, 1); // isn't this the default? --SDM 
#endif 

    // install the SIGFPE handler 

    // In addition to handling SIGINT, also handle SIGFPE by ignoring it. 
    // Apparently IEEE requires floating-point exceptions to be ignored by 
    // default, but alpha-dec-osf3 doesn't seem to do so. 

    // Commented out by SDM 2/7/2002: this causes an infinite loop on 
    // some architectures when an integer division by zero occurs: we 
    // don't recover from the floating point exception, and the 
    // program just generates another one immediately. 
#if 0 
    action.sa_handler = SIG_IGN; 
    sigemptyset(&action.sa_mask); 
    action.sa_flags = 0; 
    if (sigaction(SIGFPE, &action, &oact) != 0) { 
    sysErrorBelch("warning: failed to install SIGFPE handler"); 
} 
#endif 

#ifdef alpha_HOST_ARCH 
    ieee_set_fp_control(0); 
#endif 

    // ignore SIGPIPE; see #1619 
    // actually, we use an empty signal handler rather than SIG_IGN, 
    // so that SIGPIPE gets reset to its default behaviour on exec. 
    action.sa_handler = empty_handler; 
    sigemptyset(&action.sa_mask); 
    action.sa_flags = 0; 
    if (sigaction(SIGPIPE, &action, &oact) != 0) { 
sysErrorBelch("warning: failed to install SIGPIPE handler"); 
    } 

    set_sigtstp_action(rtsTrue); 
} 

tym, można zobaczyć, że GHC instaluje przynajmniej Sigint i SIGPIPE ładowarki. Nie wiem, czy w kodzie źródłowym są ukryte inne moduły obsługi sygnałów.

+2

Dobra robota. Wygląda więc na to, że 'SIGINT' jest jedynym sygnałem ze specjalnym traktowaniem ... – MathematicalOrchid

16

Googling „Haskell haczyk SIGTERM” doprowadziło mnie do System.Posix.Signals z pakietu unix, który ma dość ładnie wyglądający system do przechwytywania i obsługi tych sygnałów. Wystarczy przewinąć w dół do sekcji "Obsługa sygnałów".

EDIT: trywialny przykład:

import System.Posix.Signals 
import Control.Concurrent (threadDelay) 
import Control.Concurrent.MVar 

termHandler :: MVar() -> Handler 
termHandler v = CatchOnce $ do 
    putStrLn "Caught SIGTERM" 
    putMVar v() 

loop :: MVar() -> IO() 
loop v = do 
    putStrLn "Still running" 
    threadDelay 1000000 
    val <- tryTakeMVar v 
    case val of 
     Just _ -> putStrLn "Quitting" >> return() 
     Nothing -> loop v 

main = do 
    v <- newEmptyMVar 
    installHandler sigTERM (termHandler v) Nothing 
    loop v 

Zauważ, że musiałem użyć MVar poinformować loop, że nadszedł czas, aby zamknąć. Próbowałem użyć exitSuccess z System.Exit, ale ponieważ termHandler jest wykonywany w wątku, który nie jest głównym, nie może spowodować, że program zostanie zamknięty. Może być łatwiejszy sposób, ale nigdy wcześniej nie korzystałem z tego modułu, więc nie znam żadnego z nich. Przetestowałem to na Ubuntu 12.10.

+1

Ta biblioteka wygląda na bardzo istotną, jeśli rzeczywiście muszę zastąpić domyślne działania. Nadal chciałbym wiedzieć, jakie są te domyślne ustawienia. ;-) – MathematicalOrchid

+0

Mój błąd. Przyglądanie się źródłu tego modułu również nie mówi mi zbyt wiele. Próbowałem kilka różnych sygnałów i wydaje się, że domyślnym działaniem, gdy którykolwiek z nich jest wysyłany do tego procesu, jest po prostu zatrzymanie procesu. – bheklilr

+1

Nie trzeba przepraszać; Twoje informacje z pewnością wyglądają na przydatne. – MathematicalOrchid