Ich sehe ein sehr seltsames Verhalten, bei dem sich Haskells bracket
Funktion je nach Verwendung stack run
oder stack test
Verwendung unterschiedlich verhält .
Betrachten Sie den folgenden Code, in dem zwei verschachtelte Klammern zum Erstellen und Bereinigen von Docker-Containern verwendet werden:
module Main where
import Control.Concurrent
import Control.Exception
import System.Process
main :: IO ()
main = do
bracket (callProcess "docker" ["run", "-d", "--name", "container1", "registry:2"])
(\() -> do
putStrLn "Outer release"
callProcess "docker" ["rm", "-f", "container1"]
putStrLn "Done with outer release"
)
(\() -> do
bracket (callProcess "docker" ["run", "-d", "--name", "container2", "registry:2"])
(\() -> do
putStrLn "Inner release"
callProcess "docker" ["rm", "-f", "container2"]
putStrLn "Done with inner release"
)
(\() -> do
putStrLn "Inside both brackets, sleeping!"
threadDelay 300000000
)
)
Wenn ich dies mit ausführe stack run
und mit unterbreche Ctrl+C
, erhalte ich die erwartete Ausgabe:
Inside both brackets, sleeping!
^CInner release
container2
Done with inner release
Outer release
container1
Done with outer release
Und ich kann überprüfen, ob beide Docker-Container erstellt und dann entfernt wurden.
Wenn ich jedoch genau denselben Code in einen Test einfüge und ausführe stack test
, erfolgt nur (ein Teil) der ersten Bereinigung:
Inside both brackets, sleeping!
^CInner release
container2
Dies führt dazu, dass ein Docker-Container auf meinem Computer ausgeführt wird. Was ist los?
- Ich habe dafür gesorgt, dass genau dasselbe
ghc-options
an beide weitergegeben wird. - Vollständiges Demonstrations-Repo hier: https://github.com/thomasjm/bracket-issue
.stack-work
und sie direkt ausführe, tritt das Problem nicht auf. Es passiert nur, wenn man unter läuft stack test
.
stack test
Startet Worker-Threads, um Tests durchzuführen. 2) Der SIGINT-Handler beendet den Haupt-Thread. 3) Haskell-Programme werden beendet, wenn der Haupt-Thread dies tut, wobei zusätzliche Threads ignoriert werden. 2 ist das Standardverhalten von SIGINT für von GHC kompilierte Programme. 3 ist, wie Threads in Haskell funktionieren. 1 ist eine vollständige Vermutung.