Ben Haskell'ın çok garip bir davranış görüyorum bracket
işlevi farklı davranıyor olmasına bağlı olduğu stack run
veya stack test
kullanılır.
Docker kapsayıcılarını oluşturmak ve temizlemek için iki iç içe parantez kullanılan aşağıdaki kodu göz önünde bulundurun:
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
)
)
Bu ile çalıştırın stack run
ve kesildiğinde Ctrl+C
, beklenen çıktıyı alıyorum:
Inside both brackets, sleeping!
^CInner release
container2
Done with inner release
Outer release
container1
Done with outer release
Ve her iki Docker kapsayıcısının da oluşturulduğunu ve kaldırıldığını doğrulayabilirim.
Ancak, bu aynı kodu bir sınama yapıştırın ve çalıştırırsanız stack test
, ilk temizleme yalnızca (bir kısmı) gerçekleşir:
Inside both brackets, sleeping!
^CInner release
container2
Bu, bir Docker konteynerinin makinemde çalışmasına neden olur. Neler oluyor?
- Aynı şeyin
ghc-options
her ikisine de aktarıldığından emin oldum . - Burada tam demo repo: https://github.com/thomasjm/bracket-issue
.stack-work
doğrudan çalıştırırsam, sorun olmaz. Sadece altında koşarken olur stack test
.
stack test
İşçilerin iş parçacıklarını testleri yürütmeye başlar. 2) SIGINT tutucusu ana ipliği öldürür. 3) Haskell programları, ana iş parçacığı ek bir iş parçasını yok sayarak sona erer. 2, GHC tarafından derlenen programlar için SIGINT'teki varsayılan davranıştır. 3 Haskell'de ipliklerin nasıl çalıştığıdır. 1 tam bir tahmindir.