Signals in Haskell
Our first example demonstrates how to handle Unix signals in Haskell. We’ll create a program that gracefully handles SIGINT and SIGTERM signals.
import System.Posix.Signals
import Control.Concurrent (forkIO, threadDelay)
import Control.Concurrent.MVar
main :: IO ()
main = do
-- Create an MVar to act as a signal between threads
done <- newEmptyMVar
-- Set up signal handlers
installHandler sigINT (Catch $ handleSignal "SIGINT" done) Nothing
installHandler sigTERM (Catch $ handleSignal "SIGTERM" done) Nothing
-- Fork a thread to simulate some work
forkIO $ do
putStrLn "Awaiting signal"
threadDelay 100000000 -- Sleep for 100 seconds
-- Wait for a signal
takeMVar done
putStrLn "Exiting"
handleSignal :: String -> MVar () -> IO ()
handleSignal sigName done = do
putStrLn $ "\nReceived " ++ sigName
putMVar done ()In this Haskell version, we use the System.Posix.Signals module to handle Unix signals. Here’s a breakdown of the code:
We import necessary modules for signal handling, concurrency, and inter-thread communication.
In the
mainfunction, we create anMVarcalleddone. This will act as a channel for signaling between threads.We set up signal handlers for SIGINT and SIGTERM using
installHandler. Each handler calls thehandleSignalfunction with the appropriate signal name and thedoneMVar.We fork a new thread that simulates some work by sleeping for 100 seconds. This is analogous to the main work of a server or long-running process.
The main thread then waits on the
doneMVar usingtakeMVar. This blocks until a signal is received and handled.The
handleSignalfunction prints the name of the received signal and puts a value into thedoneMVar, which unblocks the main thread.
When we run this program, it will block waiting for a signal. By typing Ctrl-C, we can send a SIGINT signal, causing the program to print the signal name and then exit.
$ runhaskell signals.hs
Awaiting signal
^C
Received SIGINT
ExitingThis Haskell implementation uses MVars for inter-thread communication, which is conceptually similar to channels in other languages. The forkIO function is used to create a new thread, analogous to goroutines in Go.
While the structure is different from the original Go code, this Haskell version achieves the same functionality of gracefully handling Unix signals.
Comments powered by Disqus