Подтвердить что ты не робот

Как написать обработчик Ctrl-C в Haskell?

Я попробовал следующий подход:

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

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

Но он выводит только:

^CTest.hs: ExitSuccess

on Ctrl-C, вместо выхода. Как я должен делать это правильно?

4b9b3361

Ответ 1

Из документов installHandler:

установлен обработчик, который будет вызывать действие в новом потоке, когда (или вскоре после этого) будет получен сигнал.

и exitWith:

Примечание: в GHC exitWith должен вызываться из основного потока программы, чтобы выйти из процесса. Когда вызывается из другого потока, exitWith будет генерировать ExitException как обычно, но исключение не приведет к выходу самого процесса.

Итак, обработчик exitSuccess не завершает процесс и не ожидает ожидаемого (хотя и неожиданного;) поведения.

Если вы хотите немедленное действие,

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

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

убивает поток сразу после получения сигнала.

Менее радикально, если вы хотите успешный выход, будет

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)

Я думаю, что он также будет работать надежно, но я не совсем уверен.