2013-08-25 21 views
14

Wenn ich Strg + C drücke, löst dies eine Ausnahme aus (immer in Thread 0?). Sie können dies erfassen, wenn Sie möchten - oder, was wahrscheinlicher ist, führen Sie eine Bereinigung durch und dann erneut. Aber das übliche Ergebnis ist, das Programm auf die eine oder andere Weise zum Stillstand zu bringen.Killing eine Haskell-Binärdatei

Angenommen, ich verwende den Unix-Befehl kill. Wie ich es verstehe, sendet kill grundsätzlich ein (konfigurierbares) Unix-Signal an den angegebenen Prozess.

Wie reagiert der Haskell RTS darauf? Ist es irgendwo dokumentiert? Ich würde vorstellen die SIGTERM Senden die gleiche Wirkung wie das Drücken von Strg + C haben würde, aber ich weiß nicht, dass für eine Tatsache ...

(Und natürlich können Sie kill verwenden, um Signale zu senden, haben nichts zu tun mit dem töten. noch einmal, ich würde vorstellen, dass die RTS ignorieren würde, sagen wir, SIGHUP oder SIGPWR, aber ich weiß es nicht sicher.)

+3

Ctrl-C sendet 'SIGINT'. Ich würde erwarten, dass "SIGTERM" anders behandelt wird als "SIGINT". –

+2

Ich denke, es gibt eine Standardaktion für alle von Posix und/oder dem spezifischen System definierten Signale, siehe hier: http://man7.org/linux/man-pages/man7/signal.7.html (Scrollen Sie nach unten zum Tabelle). – bennofs

+1

@bennofs Gut zu wissen. Die Standardaktion für 'SIGINT' scheint es zu sein, den Prozess zu beenden, doch der RTS behandelt dies eindeutig speziell. Es wäre schön zu wissen, ob irgendwelche anderen Signale spezielle Behandlung erhalten ... – MathematicalOrchid

Antwort

12

Suche nach "Signal" im ghc source code auf Github zeigte die installDefaultSignals Funktion:

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); 
} 

Von diesem können Sie sehen, dass GHC mindestens SIGINT und SIGPIPE Handler installiert. Ich weiß nicht, ob noch andere Signalhandler im Quellcode versteckt sind.

+2

Gute Arbeit. So scheint es, dass "SIGINT" das einzige Signal mit besonderer Behandlung ist ... – MathematicalOrchid

16

mich googeln „Haskell fangen SIGTERM“ geführt zu System.Posix.Signals des unix-Pakets, das ein ziemlich gut aussehendes System zum Erfassen und Behandeln dieser Signale hat. Scrollen Sie einfach nach unten zum Abschnitt "Handhabung von Signalen".

EDIT: Ein triviales Beispiel:

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 

Beachten Sie, dass ich eine MVar verwenden musste loop informieren, dass es an der Zeit zu beenden war. Ich versuchte mit exitSuccess von System.Exit, aber da termHandler in einem Thread ausgeführt wird, der nicht der wichtigste ist, kann es nicht dazu führen, dass das Programm beendet wird. Es könnte einen einfacheren Weg geben, aber ich habe dieses Modul noch nie benutzt, daher kenne ich es nicht. Ich habe das auf Ubuntu 12.10 getestet.

+1

Diese Bibliothek sieht _highly_ relevant aus, wenn ich tatsächlich die Standardaktionen überschreiben muss. Ich würde immer noch gerne wissen, was diese Vorgaben sind. ;-) – MathematicalOrchid

+0

Mein Fehler. Die Quelle dieses Moduls zu sehen, sagt mir auch nicht viel. Ich habe mehrere verschiedene Signale ausprobiert und es scheint, dass die Standardaktion, wenn einer dieser Prozesse an diesen Prozess gesendet wird, darin besteht, den Prozess einfach zu stoppen. – bheklilr

+1

Keine Notwendigkeit, sich zu entschuldigen; Ihre Informationen sehen sicherlich nützlich aus. – MathematicalOrchid

Verwandte Themen