Skip to content

Commit f5589a0

Browse files
ana-pantiliettuegelrv-jenkins
authored
Handle Z3 exceptions (#1998)
* Handle Z3 exceptions * Fix * Remove unused import * Remove unused import * Address review comments + refactor * throwSolverException: Wrap any synchronous exception * Lint Co-authored-by: Thomas Tuegel <thomas.tuegel@runtimeverification.com> Co-authored-by: rv-jenkins <admin@runtimeverification.com>
1 parent a0876de commit f5589a0

File tree

2 files changed

+73
-25
lines changed

2 files changed

+73
-25
lines changed

kore/src/SMT.hs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ module SMT
2929
, declareFun_
3030
, setInfo
3131
, NoSMT (..), runNoSMT
32+
, SimpleSMT.SolverException (..)
3233
-- * Expressions
3334
, SExpr (..)
3435
, SimpleSMT.Logger
@@ -48,7 +49,9 @@ module SMT
4849
, SimpleSMT.existsQ
4950
) where
5051

51-
import Prelude
52+
import Prelude.Kore hiding
53+
( assert
54+
)
5255

5356
import Control.Concurrent.MVar
5457
import Control.Exception

kore/src/SMT/SimpleSMT.hs

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ module SMT.SimpleSMT
2626
, simpleCommand
2727
, simpleCommandMaybe
2828
, loadFile
29+
, SolverException (..)
2930

3031
-- ** S-Expressions
3132
, SExpr(..)
@@ -151,12 +152,14 @@ module SMT.SimpleSMT
151152
, existsQ
152153
) where
153154

154-
import Prelude hiding
155+
import Prelude.Kore hiding
155156
( abs
156157
, and
158+
, assert
157159
, concat
158160
, const
159161
, div
162+
, extract
160163
, mod
161164
, not
162165
, or
@@ -166,8 +169,13 @@ import qualified Colog
166169
import Control.Concurrent
167170
( forkIO
168171
)
172+
import Control.Exception
173+
( AsyncException
174+
, SomeException (..)
175+
)
169176
import qualified Control.Exception as X
170177
import qualified Control.Monad as Monad
178+
import qualified Control.Monad.Catch as Exception
171179
import Data.Bits
172180
( testBit
173181
)
@@ -176,6 +184,9 @@ import Data.Ratio
176184
, numerator
177185
, (%)
178186
)
187+
import Data.String
188+
( fromString
189+
)
179190
import Data.Text
180191
( Text
181192
)
@@ -193,7 +204,7 @@ import Numeric
193204
)
194205
import qualified Prelude
195206
import System.Exit
196-
( ExitCode
207+
( ExitCode (..)
197208
)
198209
import System.IO
199210
( Handle
@@ -203,6 +214,7 @@ import System.IO
203214
)
204215
import System.Process
205216
( ProcessHandle
217+
, getProcessExitCode
206218
, runInteractiveProcess
207219
, waitForProcess
208220
)
@@ -219,6 +231,7 @@ import Kore.Log.DebugSolver
219231
, logDebugSolverSendWith
220232
)
221233
import qualified Log
234+
import qualified Pretty
222235
import SMT.AST
223236

224237
-- ---------------------------------------------------------------------
@@ -266,6 +279,37 @@ data SolverHandle = SolverHandle
266279
, hProc :: !ProcessHandle
267280
}
268281

282+
data SolverException =
283+
SolverException
284+
{ exitCode :: !(Maybe ExitCode)
285+
, someException :: !Exception.SomeException
286+
}
287+
deriving (Show, Typeable)
288+
289+
instance Exception.Exception SolverException where
290+
displayException SolverException { exitCode, someException } =
291+
(show . Pretty.vsep . catMaybes)
292+
[ Just "Error while communicating with the solver:"
293+
, Just $ Pretty.indent 4 $ prettyException someException
294+
, (Pretty.<+>) "Solver exit code:" . prettyExitCode <$> exitCode
295+
]
296+
where
297+
prettyException =
298+
Pretty.vsep . map fromString . lines . Exception.displayException
299+
prettyExitCode ExitSuccess = "0"
300+
prettyExitCode (ExitFailure code) = Pretty.pretty code
301+
302+
throwSolverException :: ProcessHandle -> SomeException -> IO a
303+
throwSolverException solverHandle someException
304+
| Just _ <- Exception.fromException someException :: Maybe AsyncException =
305+
Exception.throwM someException
306+
| otherwise = do
307+
exitCode <- getProcessExitCode solverHandle
308+
Exception.throwM SolverException { exitCode, someException }
309+
310+
trySolver :: ProcessHandle -> IO a -> IO a
311+
trySolver hProc = Exception.handle (throwSolverException hProc)
312+
269313
-- | Start a new solver process.
270314
newSolver
271315
:: FilePath -- ^ Executable
@@ -307,18 +351,20 @@ warn :: HasCallStack => Solver -> Text -> IO ()
307351
warn = logMessageWith Log.Warning
308352

309353
send :: Solver -> SExpr -> IO ()
310-
send Solver { solverHandle = SolverHandle { hIn }, logger } command' = do
311-
logDebugSolverSendWith logger command'
312-
sendSExpr hIn command'
313-
hPutChar hIn '\n'
314-
hFlush hIn
354+
send Solver { solverHandle = SolverHandle { hIn, hProc }, logger } command' =
355+
trySolver hProc $ do
356+
logDebugSolverSendWith logger command'
357+
sendSExpr hIn command'
358+
hPutChar hIn '\n'
359+
hFlush hIn
315360

316361
recv :: Solver -> IO SExpr
317-
recv Solver { solverHandle = SolverHandle { hOut } , logger } = do
318-
responseLines <- readResponse 0 []
319-
let resp = Text.unlines (reverse responseLines)
320-
logDebugSolverRecvWith logger resp
321-
readSExpr resp
362+
recv Solver { solverHandle = SolverHandle { hOut, hProc } , logger } =
363+
trySolver hProc $ do
364+
responseLines <- readResponse 0 []
365+
let resp = Text.unlines (reverse responseLines)
366+
logDebugSolverRecvWith logger resp
367+
readSExpr resp
322368
where
323369
{-| Reads an SMT response.
324370
@@ -345,17 +391,17 @@ command solver c =
345391
recv solver
346392

347393
stop :: Solver -> IO ExitCode
348-
stop solver@Solver { solverHandle = SolverHandle { hIn, hOut, hErr, hProc } } = do
349-
send solver (List [Atom "exit"])
350-
ec <- waitForProcess hProc
351-
let handler :: X.IOException -> IO ()
352-
handler ex = (debug solver . Text.pack) (show ex)
353-
X.handle handler $ do
354-
hClose hIn
355-
hClose hOut
356-
hClose hErr
357-
return ec
358-
394+
stop solver@Solver { solverHandle = SolverHandle { hIn, hOut, hErr, hProc } } =
395+
trySolver hProc $ do
396+
send solver (List [Atom "exit"])
397+
ec <- waitForProcess hProc
398+
let handler :: X.IOException -> IO ()
399+
handler ex = (debug solver . Text.pack) (show ex)
400+
X.handle handler $ do
401+
hClose hIn
402+
hClose hOut
403+
hClose hErr
404+
return ec
359405

360406
-- | Load the contents of a file.
361407
loadFile :: Solver -> FilePath -> IO ()
@@ -366,7 +412,6 @@ loadFile s file = do
366412
Right exprs ->
367413
mapM_ (command s) exprs
368414

369-
370415
-- | A command with no interesting result.
371416
ackCommand :: Solver -> SExpr -> IO ()
372417
ackCommand solver c =

0 commit comments

Comments
 (0)