Skip to content

Commit

Permalink
Simplify obligation-proving timeouts by not catching exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
langston-barrett committed Jun 25, 2024
1 parent 63a560f commit ae52603
Show file tree
Hide file tree
Showing 5 changed files with 13 additions and 37 deletions.
2 changes: 0 additions & 2 deletions crucible-cli/src/Lang/Crucible/CLI.hs
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,6 @@ simulateProgramWithExtension mkExt fn theInput outh profh opts hooks =
Prove.Unknown {} -> hPutStrLn outh "UNKNOWN"
case merr of
Left CTO.TimedOut -> hPutStrLn outh $ unlines ["TIMEOUT"]
Left (CTO.Exception exn) ->
hPutStrLn outh $ unlines ["EXCEPTION", show exn]
Right () -> pure ()

_ -> hPutStrLn outh "No suitable main function found"
Expand Down
1 change: 0 additions & 1 deletion crucible-symio/tests/TestMain.hs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ runFSTest' bak (FSTest fsTest) = do
T.assertFailure "Assertion Failure"
case merr of
Left CTO.TimedOut -> T.assertFailure "Timeout"
Left (CTO.Exception exn) -> T.assertFailure ("Exception: " ++ show exn)
Right () -> pure ()

showAbortedResult :: CS.AbortedResult c d -> String
Expand Down
1 change: 0 additions & 1 deletion crucible-syntax/src/Lang/Crucible/Syntax/Overrides.hs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ proveObligations =
CB.Unknown {} -> hPutStrLn h $ unlines ["Proof inconclusive!", show $ ppSimError $ (proofGoal o)^.labeledPredMsg]
case merr of
Left CTO.TimedOut -> hPutStrLn h $ unlines ["Proof timed out!"]
Left (CTO.Exception exn) -> hPutStrLn h $ unlines ["Exception during proof!", show exn]
Right () -> pure ()

clearProofObligations bak
6 changes: 3 additions & 3 deletions crucible/src/Lang/Crucible/Backend/Prove.hs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ import qualified What4.Solver.Adapter as WSA

import qualified Lang.Crucible.Backend as CB
import Lang.Crucible.Backend.Assumptions (Assumptions)
import Lang.Crucible.Utils.Timeout (Timeout, TimeoutError)
import Lang.Crucible.Utils.Timeout (Timeout, TimedOut)
import qualified Lang.Crucible.Utils.Timeout as CTO

-- | Local helper
Expand Down Expand Up @@ -258,7 +258,7 @@ offlineProve sym ld adapter asmps goal k =
liftIO (offlineProveIO sym ld adapter asmps goal k)

offlineProveWithTimeout ::
MonadError TimeoutError m =>
MonadError TimedOut m =>
MonadIO m =>
(sym ~ WE.ExprBuilder t st fs) =>
W4.IsSymExprBuilder sym =>
Expand All @@ -275,7 +275,7 @@ offlineProveWithTimeout to sym ld adapter asmps goal k = do
liftEither r

offlineProver ::
MonadError TimeoutError m =>
MonadError TimedOut m =>
MonadIO m =>
(sym ~ WE.ExprBuilder t st fs) =>
Timeout ->
Expand Down
40 changes: 10 additions & 30 deletions crucible/src/Lang/Crucible/Utils/Timeout.hs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
module Lang.Crucible.Utils.Timeout
( Timeout(..)
, TimeoutError(..)
, TimedOut(..)
, withTimeout
) where

import qualified Control.Concurrent as CC
import qualified Control.Concurrent.Async as CCA
import Control.Exception.Base (SomeException)

import qualified Lang.Crucible.Utils.Seconds as Secs

Expand All @@ -18,41 +17,22 @@ newtype Timeout = Timeout { getTimeout :: Secs.Seconds }
timeoutToMicros :: Timeout -> Int
timeoutToMicros = Secs.secondsToMicroseconds . getTimeout

-- Private, not exported
data DidTimeOut = DidTimeOut

-- | An error resulting from 'withTimeout'.
data TimeoutError
= -- | The task timed out
TimedOut
-- | Some other exception ocurred
| Exception SomeException
-- | A task timed out.
data TimedOut = TimedOut
deriving Show

-- | Execute a task with a timeout.
--
-- Catches any exceptions that occur during the task, returning them as
-- @'Left' ('Exception' exn)@.
-- Implemented via 'CCA.race', so re-throws exceptions that occur during the
-- task (if it completes before the timeout).
withTimeout ::
-- | Timeout duration (seconds)
Timeout ->
-- | Task to attempt
IO a ->
IO (Either TimeoutError a)
IO (Either TimedOut a)
withTimeout to task = do
worker <- CCA.async task
timeout <- CCA.async $ do
CC.threadDelay (timeoutToMicros to)
CCA.cancel worker
return DidTimeOut
res <- CCA.waitEitherCatch timeout worker
case res of
Left (Right DidTimeOut) -> do
return (Left TimedOut)
Left (Left exn) -> do
return (Left (Exception exn))
Right (Left exn) -> do
return (Left (Exception exn))
Right (Right val) ->
return (Right val)

let timeout = do
CC.threadDelay (timeoutToMicros to)
pure TimedOut
CCA.race timeout task

0 comments on commit ae52603

Please sign in to comment.