ฉันเห็นพฤติกรรมแปลก ๆ ที่bracket
หน้าที่ของ Haskell ทำงานแตกต่างกันไปขึ้นอยู่กับว่ามีการใช้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
นั้นถูกส่งผ่านไปยังทั้งคู่ - repo สาธิตเต็มรูปแบบที่นี่: https://github.com/thomasjm/bracket-issue
.stack-work
รันและรันโดยตรงปัญหาจะไม่เกิดขึ้น stack test
มันจะเกิดขึ้นเมื่อมีการทำงานภายใต้
stack test
เริ่มเธรดผู้ปฏิบัติงานเพื่อจัดการทดสอบ 2) ตัวจัดการ SIGINT ฆ่าเธรดหลัก 3) โปรแกรม Haskell จะสิ้นสุดเมื่อเธรดหลักทำโดยไม่สนใจเธรดเพิ่มเติมใด ๆ 2 คือพฤติกรรมเริ่มต้นบน SIGINT สำหรับโปรแกรมที่รวบรวมโดย GHC 3 คือการทำงานของเธรดใน Haskell 1 เป็นการเดาที่สมบูรณ์