@@ -29,6 +29,7 @@ import Control.Monad.Logger
29
29
import Control.Monad.Trans.State
30
30
import Data.ByteString.Builder qualified as BS
31
31
import Data.ByteString.Char8 qualified as BS
32
+ import Data.IORef
32
33
import Data.Text (Text , pack )
33
34
import SMTLIB.Backends qualified as Backend
34
35
import SMTLIB.Backends.Process qualified as Backend
@@ -72,8 +73,10 @@ defaultSMTOptions =
72
73
73
74
data SMTContext = SMTContext
74
75
{ 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 () )
77
80
, mbTranscriptHandle :: Maybe Handle
78
81
, prelude :: [DeclareCommand ]
79
82
}
@@ -93,7 +96,9 @@ mkContext ::
93
96
io SMTContext
94
97
mkContext opts prelude = do
95
98
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
97
102
mbTranscriptHandle <- forM opts. transcript $ \ path -> do
98
103
logMessage $ " Transcript in file " <> pack path
99
104
liftIO $ do
@@ -107,7 +112,7 @@ mkContext opts prelude = do
107
112
pure
108
113
SMTContext
109
114
{ solver
110
- , solverClose = Backend. close handle
115
+ , solverClose
111
116
, mbTranscriptHandle
112
117
, prelude
113
118
, options = opts
@@ -122,7 +127,7 @@ closeContext ctxt = do
122
127
logMessage (" Stopping SMT solver" :: Text )
123
128
whenJust ctxt. mbTranscriptHandle $ \ h -> liftIO $ do
124
129
BS. hPutStrLn h " ; stopping solver\n ;;;;;;;;;;;;;;;;;;;;;;;"
125
- liftIO ctxt. solverClose
130
+ liftIO $ join $ readIORef ctxt. solverClose
126
131
127
132
{- | Close the connection to the SMT solver process and all other resources in @SMTContext@.
128
133
Using this function means completely stopping the solver with no intention of using it any more.
@@ -133,7 +138,7 @@ destroyContext ctxt = do
133
138
whenJust ctxt. mbTranscriptHandle $ \ h -> liftIO $ do
134
139
BS. hPutStrLn h " ; permanently stopping solver\n ;;;;;;;;;;;;;;;;;;;;;;;"
135
140
hClose h
136
- liftIO ctxt. solverClose
141
+ liftIO $ join $ readIORef ctxt. solverClose
137
142
138
143
connectToSolver :: LoggerMIO io => io (Backend. Solver , Backend. Handle )
139
144
connectToSolver = do
@@ -179,7 +184,7 @@ runCmd cmd = do
179
184
whenJust (comment cmd) $ \ c ->
180
185
liftIO (BS. hPutBuilder h c)
181
186
liftIO (BS. hPutBuilder h $ cmdBS <> " \n " )
182
- output <- run_ cmd ctxt. solver cmdBS
187
+ output <- (liftIO $ readIORef ctxt. solver) >>= \ solver -> run_ cmd solver cmdBS
183
188
let result = readResponse output
184
189
whenJust ctxt. mbTranscriptHandle $
185
190
liftIO . flip BS. hPutStrLn (BS. pack $ " ; " <> show output <> " , parsed as " <> show result <> " \n " )
0 commit comments