2013-08-25 79 views
14

如果我按Ctrl + C,這會拋出一個異常(總是在線程0中?)。如果你願意,你可以抓住這個 - 或者更可能的是,運行一些清理工作然後重新拋出它。但通常的結果是讓程序停頓,無論如何。殺死一個Haskell二進制

現在假設我使用Unix kill命令。據我所知,kill基本上發送一個(可配置的)Unix信號到指定的進程。

Haskell RTS如何迴應?它是否記錄在某處?我會想象,在發送SIGTERM將不得不爲按Ctrl + C相同的效果,但我不知道那是事實...

(當然,你可以使用kill發送信號,那什麼都沒有做殺害的。同樣,我會想象的RTS會忽略,比如,SIGHUPSIGPWR,但我不知道。)

+3

Ctrl-C發送'SIGINT'。我希望'SIGTERM'與'SIGINT'的處理方式不同。 –

+2

我認爲所有由Posix和/或特定系統定義的信號都有一個默認行爲,請參見:http://man7.org/linux/man-pages/man7/signal.7.html(向下滾動到表)。 – bennofs

+1

@bennofs很高興知道。 'SIGINT'的默認操作似乎是終止進程,但RTS明確地處理這個問題。很高興知道是否有其他信號接收到特殊處理... – MathematicalOrchid

回答

12

搜索在ghc source code在github上的「信號」透露了installDefaultSignals功能:

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

從這裏,你可以看到,GHC安裝至少SIGINT和SIGPIPE處理程序。我不知道是否有任何其他信號處理程序隱藏在源代碼中。

+2

良好的工作。所以看起來'SIGINT'是唯一有特殊待遇的信號...... – MathematicalOrchid

16

谷歌搜索「哈斯克爾捕捉SIGTERM」導致我到unix包的System.Posix.Signals,它有一個相當漂亮的捕捉和處理這些信號的系統。只需向下滾動到「處理信號」部分。

編輯:一個簡單的例子:

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 

注意,我不得不使用的無功通知loop,是時候退出。我試過從System.Exit使用exitSuccess,但由於termHandler在非主線程中執行,它不能導致程序退出。可能有一個更簡單的方法來做到這一點,但我從來沒有使用過這個模塊,所以我不知道它。我在Ubuntu 12.10上測試了這個。

+1

如果確實需要覆蓋默認操作,則此庫看起來很重要。我仍然想知道這些默認設置是什麼。 ;-) – MathematicalOrchid

+0

我的錯誤。查看該模塊的來源也沒有告訴我很多。我嘗試了幾個不同的信號,看起來這些過程中的任何一個發送到該過程時的默認操作就是停止過程。 – bheklilr

+1

不需要道歉;你的信息當然很有用。 – MathematicalOrchid