Estou tendo problemas com o de Haskell bracket
: ao ser executado dentro de um segundo argumento de um segmento bifurcado (usando forkFinally
) bracket
, o cálculo que libera recursos não é executado quando o programa termina.
Aqui está o código que ilustra o problema (sei que, nesse caso específico, eu poderia desativar o buffer para gravar no arquivo imediatamente):
import System.IO
import Control.Exception ( bracket
, throwTo
)
import Control.Concurrent ( forkFinally
, threadDelay
)
main = do
threadId <- forkFinally
(writeToFile "first_file")
(\ex -> putStrLn $ "Exception occurred: " ++ show ex)
putStrLn "Press enter to exit"
_ <- getLine
putStrLn "Bye!"
writeToFile :: FilePath -> IO ()
writeToFile file = bracket
(openFile file AppendMode)
(\fileHandle -> do
putStrLn $ "\nClosing handle " ++ show fileHandle
hClose fileHandle
)
(\fileHandle -> mapM_ (addNrAndWait fileHandle) [1 ..])
addNrAndWait :: Handle -> Int -> IO ()
addNrAndWait fileHandle nr =
let nrStr = show nr
in do
putStrLn $ "Appending " ++ nrStr
hPutStrLn fileHandle nrStr
threadDelay 1000000
A computação que libera recursos (e grava no console) nunca é chamada:
putStrLn $ "\nClosing handle " ++ show fileHandle
hClose fileHandle
Tornar o programa único, removendo o código de bifurcação, elimina main
o problema e o identificador do arquivo é fechado ao finalizar o programa com Ctrl+ c:
main = writeToFile "first_file"
Como garantir que o código de liberação de recurso bracket
seja executado ao usar vários threads?
threadDelay
antes da impressão"Closing handle"
.) #