@@ -29,6 +29,7 @@ import Control.Monad.Logger
2929import Control.Monad.Trans.State
3030import Data.ByteString.Builder qualified as BS
3131import Data.ByteString.Char8 qualified as BS
32+ import Data.IORef
3233import Data.Text (Text , pack )
3334import SMTLIB.Backends qualified as Backend
3435import SMTLIB.Backends.Process qualified as Backend
@@ -72,8 +73,10 @@ defaultSMTOptions =
7273
7374data SMTContext = SMTContext
7475 { options :: SMTOptions
75- , solver :: Backend. Solver
76- , solverClose :: IO ()
76+ , -- use IORef here to ensure we only ever retain one pointer to the solver,
77+ -- otherwise the solverClose action does not actually terminate the solver instance
78+ solver :: IORef Backend. Solver
79+ , solverClose :: IORef (IO () )
7780 , mbTranscriptHandle :: Maybe Handle
7881 , prelude :: [DeclareCommand ]
7982 }
@@ -93,7 +96,9 @@ mkContext ::
9396 io SMTContext
9497mkContext opts prelude = do
9598 logMessage (" Starting SMT solver" :: Text )
96- (solver, handle) <- connectToSolver
99+ (solver', handle) <- connectToSolver
100+ solver <- liftIO $ newIORef solver'
101+ solverClose <- liftIO $ newIORef $ Backend. close handle
97102 mbTranscriptHandle <- forM opts. transcript $ \ path -> do
98103 logMessage $ " Transcript in file " <> pack path
99104 liftIO $ do
@@ -107,7 +112,7 @@ mkContext opts prelude = do
107112 pure
108113 SMTContext
109114 { solver
110- , solverClose = Backend. close handle
115+ , solverClose
111116 , mbTranscriptHandle
112117 , prelude
113118 , options = opts
@@ -122,7 +127,7 @@ closeContext ctxt = do
122127 logMessage (" Stopping SMT solver" :: Text )
123128 whenJust ctxt. mbTranscriptHandle $ \ h -> liftIO $ do
124129 BS. hPutStrLn h " ; stopping solver\n ;;;;;;;;;;;;;;;;;;;;;;;"
125- liftIO ctxt. solverClose
130+ liftIO $ join $ readIORef ctxt. solverClose
126131
127132{- | Close the connection to the SMT solver process and all other resources in @SMTContext@.
128133 Using this function means completely stopping the solver with no intention of using it any more.
@@ -133,7 +138,7 @@ destroyContext ctxt = do
133138 whenJust ctxt. mbTranscriptHandle $ \ h -> liftIO $ do
134139 BS. hPutStrLn h " ; permanently stopping solver\n ;;;;;;;;;;;;;;;;;;;;;;;"
135140 hClose h
136- liftIO ctxt. solverClose
141+ liftIO $ join $ readIORef ctxt. solverClose
137142
138143connectToSolver :: LoggerMIO io => io (Backend. Solver , Backend. Handle )
139144connectToSolver = do
@@ -179,7 +184,7 @@ runCmd cmd = do
179184 whenJust (comment cmd) $ \ c ->
180185 liftIO (BS. hPutBuilder h c)
181186 liftIO (BS. hPutBuilder h $ cmdBS <> " \n " )
182- output <- run_ cmd ctxt. solver cmdBS
187+ output <- (liftIO $ readIORef ctxt. solver) >>= \ solver -> run_ cmd solver cmdBS
183188 let result = readResponse output
184189 whenJust ctxt. mbTranscriptHandle $
185190 liftIO . flip BS. hPutStrLn (BS. pack $ " ; " <> show output <> " , parsed as " <> show result <> " \n " )
0 commit comments