2012-11-18 2 views
18

Ho provato il seguente approccio:Come scrivere il gestore Ctrl-C in Haskell?

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

main :: IO() 
main = do 
    installHandler keyboardSignal (Catch (do exitSuccess)) Nothing 
    threadDelay (1000000000) 

Ma emettere solo:

^CTest.hs: ExitSuccess 

su Ctrl-C, invece di uscire. Come dovrei farlo correttamente?

risposta

20

Dalla documentazione di installHandler:

un gestore è installato che richiamerà azione in un nuovo thread quando (o poco dopo) il segnale viene ricevuto.

e exitWith:

Nota: in GHC, exitWith dovrebbe essere chiamato dal thread programma principale per uscire dal processo. Quando chiamato da un altro thread, exitWith genererà ExitException normalmente, ma l'eccezione non causerà l'uscita del processo stesso.

Quindi un gestore di exitSuccess non termina il processo e il comportamento previsto (anche se inatteso;).

Se si vuole un intervento immediato,

import System.Exit 
import System.Posix.Signals 
import Control.Concurrent 

main :: IO() 
main = do 
    tid <- myThreadId 
    installHandler keyboardSignal (Catch (killThread tid)) Nothing 
    threadDelay (1000000000) 

uccide il filo immediatamente dopo aver ricevuto il segnale.

meno drastica, se si vuole uscire con successo, sarebbe

import System.Exit 
import System.Posix.Signals 
import Control.Concurrent 
import qualified Control.Exception as E 

main :: IO() 
main = do 
    tid <- myThreadId 
    installHandler keyboardSignal (Catch (E.throwTo tid ExitSuccess)) Nothing 
    threadDelay (10000000) 

penso che sarà anche funzionare in modo affidabile, ma non sono del tutto sicuro.

+0

Cosa fa la riga 'threadDelay (10000000)'? – Langston

+1

['threadDelay'] (http://hackage.haskell.org/package/base-4.8.1.0/docs/Control-Concurrent.html#v:threadDelay)" Sospende il thread corrente per un dato numero di microsecondi ", simile a 'usleep' in C. Qui, sospendiamo l'esecuzione al solo scopo di dare all'utente il tempo sufficiente per premere Ctrl-C. –