나는 하스켈의 아주 이상한 행동을보고 있어요 bracket
함수가 다르게 행동 여부에 따라 있습니다 stack run
또는 stack test
사용됩니다.
Docker 컨테이너를 만들고 정리하는 데 두 개의 중첩 된 괄호가 사용되는 다음 코드를 고려하십시오.
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
)
)
로 이것을 실행 stack run
하고로 인터럽트 Ctrl+C
하면 예상 출력이 나타납니다.
Inside both brackets, sleeping!
^CInner release
container2
Done with inner release
Outer release
container1
Done with outer release
그리고 두 Docker 컨테이너가 모두 생성 된 다음 제거되었는지 확인할 수 있습니다.
그러나이 동일한 코드를 테스트에 붙여 넣고 실행 stack test
하면 첫 번째 정리 만 (일부) 발생합니다.
Inside both brackets, sleeping!
^CInner release
container2
결과적으로 내 컴퓨터에서 Docker 컨테이너가 계속 실행됩니다. 무슨 일이야?
- 나는 똑같은
ghc-options
것이 둘 다에 전달 되었는지 확인했습니다 . - 전체 데모 저장소 : https://github.com/thomasjm/bracket-issue
.stack-work
직접 실행하면 문제가 발생하지 않습니다. 에서 실행될 때만 발생합니다 stack test
.
stack test
작업자 스레드를 시작하여 테스트를 처리합니다. 2) SIGINT 핸들러는 메인 스레드를 종료합니다. 3) Haskell 프로그램은 메인 스레드가 종료 될 때 종료되며 추가 스레드는 무시합니다. 2는 GHC에 의해 컴파일 된 프로그램에 대한 SIGINT의 기본 동작입니다. 3은 Haskell에서 스레드가 작동하는 방식입니다. 1은 완전한 추측입니다.