Login
Immutable PageDiscussionInfoAttachments
iz/Haskell

MMA

Haskellでのシグナルハンドリング

System.Posix.Signalsに必要なものがある. unixのシグナル処理apiの単純なラッパのようだ.

シグナルをキャッチして終了処理を行う

すこしハマったのでメモ. Ctrl-CでCursesの終了処理を実行させたかった. http://stackoverflow.com/questions/13441676/how-to-write-ctrl-c-handler-in-haskell

installHandlerで登録されたシグナルハンドラは別スレッドで実行される. そんでもってghcではプログラムの終了を行えるのはメインスレッドのみ. というわけで普通に終了処理書いてもうまく動かない. 上のリンクではhandler内部でkillThread関数にメインスレッドのスレッドIDを渡している.

こんなコードを書いた

initialize :: IO ()
initialize = do 
  mainThreadId <- myThreadId
  installHandler sigINT (Catch (teardown>>killThread mainThreadId)) Nothing
  installHandler sigTERM (Catch (teardown>>killThread mainThreadId)) Nothing
  initCurses
  keypad stdScr True
  echo False -- noecho

teardown :: IO ()
teardown = endWin

main = do
  initialize
  handle handler mainloop
    where handler :: AsyncException -> IO () -- data AsyncException = ThreadKilled | ...
          handler e = exitSuccess

ただこれメインスレッドに例外投げてるだけなので自作の例外か,(もしあるなら)ダミーの何も表さない例外を使うほうがいい気がする. そしてAsyncExceptionのデータコンストラクタにUserInterruptとかいうそのものずばりなのがあった.

というわけで書き直した

initialize :: IO ()
initialize = do 
  initCurses
  keypad stdScr True
  echo False -- noecho

teardown :: IO ()
teardown = endWin

main = do
  initialize
  handle handler mainloop
    where handler :: AsyncException -> IO () -- data AsyncException = ThreadKilled | UserInterrupt | ...
          handler e = teardown >> exitSuccess

動いた. シグナルハンドラ自分で設定する必要なかった.

iz/Haskell (last edited 2013-05-31 11:35:41 by iz)