Skip to content

Commit 7ff00a1

Browse files
geo2agithub-actionsrv-jenkins
authored
Retry SMT queries in Booster when deciding predicates (#3889)
Fixes #3884 - refactor the SMT modules to allow re-initializing the solver dynamically: - `SMTContext` now carries the prelude and `SMTOptions` - the `closeContext` function only closes the solver handle, and does not close the solver transcript handle. The new `destroyContext` function does both. - The `SMT` monad is is changed to have `StateT SMTContext`. The `Booster.SMT.Interface.restartSolver` function restarts the solver with modified options, altering the context. Note that it does not touch the transcript handle, i.e. it will persist the sovler restarts. - the `getModelFor` and `checkPredicates` functions now have logic to retry with doubled timeout when the solver returns unknown. I'm checking-in the integration test that I was using when developing. I ran the server with `--smt-timeout 1` to observe the retry mechanism kicking-in, but I do not think it is a good idea to try to force it to retry the queries in CI. The test may still be useful when working on the SMT code in future. --------- Co-authored-by: github-actions <[email protected]> Co-authored-by: rv-jenkins <[email protected]>
1 parent 0712364 commit 7ff00a1

File tree

11 files changed

+595
-223
lines changed

11 files changed

+595
-223
lines changed

booster/library/Booster/JsonRpc.hs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ module Booster.JsonRpc (
1717

1818
import Control.Applicative ((<|>))
1919
import Control.Concurrent (MVar, putMVar, readMVar, takeMVar)
20+
import Control.Exception qualified as Exception
2021
import Control.Monad
2122
import Control.Monad.Extra (whenJust)
2223
import Control.Monad.IO.Class
@@ -148,7 +149,7 @@ respond stateVar =
148149
solver <- traverse (SMT.initSolver def) mSMTOptions
149150
result <-
150151
performRewrite doTracing def mLlvmLibrary solver mbDepth cutPoints terminals substPat
151-
whenJust solver SMT.closeSolver
152+
whenJust solver SMT.finaliseSolver
152153
stop <- liftIO $ getTime Monotonic
153154
let duration =
154155
if fromMaybe False req.logTiming
@@ -309,7 +310,7 @@ respond stateVar =
309310
pure $ Right (addHeader $ Syntax.KJAnd predicateSort result)
310311
(Left something, _) ->
311312
pure . Left . RpcError.backendError $ RpcError.Aborted $ renderText $ pretty something
312-
whenJust solver SMT.closeSolver
313+
whenJust solver SMT.finaliseSolver
313314
stop <- liftIO $ getTime Monotonic
314315

315316
let duration =
@@ -389,12 +390,12 @@ respond stateVar =
389390
"No predicates or substitutions given, returning Unknown"
390391
pure $ Left SMT.Unknown
391392
else do
392-
solver <-
393-
SMT.initSolver def smtOptions
394-
smtResult <-
395-
SMT.getModelFor solver boolPs suppliedSubst
396-
SMT.closeSolver solver
397-
pure smtResult
393+
solver <- SMT.initSolver def smtOptions
394+
result <- SMT.getModelFor solver boolPs suppliedSubst
395+
SMT.finaliseSolver solver
396+
case result of
397+
Left err -> liftIO $ Exception.throw err -- fail hard on SMT errors
398+
Right response -> pure response
398399
Log.logOtherNS "booster" (Log.LevelOther "SMT") $
399400
"SMT result: " <> pack (either show (("Subst: " <>) . show . Map.size) smtResult)
400401
pure . Right . RpcTypes.GetModel $ case smtResult of
@@ -573,7 +574,7 @@ handleSmtError = JsonRpcHandler $ \case
573574
SMT.GeneralSMTError err -> runtimeError "problem" err
574575
SMT.SMTTranslationError err -> runtimeError "translation" err
575576
SMT.SMTSolverUnknown reason premises preds -> do
576-
Log.logErrorNS "booster" "SMT returned `Unknown'"
577+
Log.logErrorNS "booster" ("SMT returned `Unknown' with reason " <> reason)
577578

578579
let bool = externaliseSort Pattern.SortBool -- predicates are terms of sort Bool
579580
externalise = Syntax.KJAnd bool . map (externalisePredicate bool) . Set.toList

0 commit comments

Comments
 (0)