Skip to content

Commit 6e4ce2f

Browse files
authored
Merge pull request #483 from viperproject/meilers_timeout
Adding an overall timeout option
2 parents 2e12ccd + 5429a24 commit 6e4ce2f

3 files changed

Lines changed: 48 additions & 21 deletions

File tree

src/main/scala/viper/carbon/Carbon.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,5 +116,12 @@ class CarbonConfig(args: Seq[String]) extends SilFrontendConfig(args, "Carbon")
116116
noshort = true
117117
)
118118

119+
val timeout = opt[Int]("timeout",
120+
descr = ("Time out after approx. n seconds. The timeout is for the whole verification in Boogie, "
121+
+ "not per method or proof obligation (default: 0, i.e. no timeout)."),
122+
default = None,
123+
noshort = true
124+
)
125+
119126
verify()
120127
}

src/main/scala/viper/carbon/CarbonVerifier.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ case class CarbonVerifier(override val reporter: Reporter,
211211
}
212212
}
213213

214+
var timeout: Option[Int] = None
215+
214216
if(config != null)
215217
{
216218
config.boogieOut.toOption match {
@@ -222,9 +224,10 @@ case class CarbonVerifier(override val reporter: Reporter,
222224
stream.close()
223225
case None =>
224226
}
227+
timeout = config.timeout.toOption
225228
}
226229

227-
invokeBoogie(_translated, options) match {
230+
invokeBoogie(_translated, options, timeout) match {
228231
case (version,result) =>
229232
if (version!=null) { dependencies.foreach(_ match {
230233
case b:BoogieDependency => b.version = version

src/main/scala/viper/carbon/verifier/BoogieInterface.scala

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ trait BoogieInterface {
7979

8080
var errormap: Map[Int, VerificationError] = Map()
8181
var models : collection.mutable.ListBuffer[String] = new collection.mutable.ListBuffer[String]
82-
def invokeBoogie(program: Program, options: Seq[String]): (String,VerificationResult) = {
82+
def invokeBoogie(program: Program, options: Seq[String], timeout: Option[Int]): (String,VerificationResult) = {
8383
// find all errors and assign everyone a unique id
8484
errormap = Map()
8585
program.visit {
@@ -88,22 +88,28 @@ trait BoogieInterface {
8888
}
8989

9090
// invoke Boogie
91-
val output = run(program.toString, defaultOptions ++ options)
92-
93-
// parse the output
94-
parse(output) match {
95-
case (version,Nil) =>
96-
(version,Success)
97-
case (version,errorIds) => {
98-
val errors = (0 until errorIds.length).map(i => {
99-
val id = errorIds(i)
100-
val error = errormap.get(id).get
101-
if (models.nonEmpty)
102-
error.failureContexts = Seq(FailureContextImpl(Some(SimpleCounterexample(Model(models(i))))))
103-
error
104-
})
105-
(version,Failure(errors))
106-
}
91+
val optOutput = run(program.toString, defaultOptions ++ options, timeout)
92+
optOutput match {
93+
case None =>
94+
// Timeout
95+
(null, Failure(Seq(TimeoutOccurred(timeout.get, "second(s)"))))
96+
case Some(output) =>
97+
// parse the output
98+
parse(output) match {
99+
case (version, Nil) =>
100+
(version, Success)
101+
case (version, errorIds) => {
102+
val errors = (0 until errorIds.length).map(i => {
103+
val id = errorIds(i)
104+
val error = errormap.get(id).get
105+
if (models.nonEmpty) {
106+
error.failureContexts = Seq(FailureContextImpl(Some(SimpleCounterexample(Model(models(i))))))
107+
}
108+
error
109+
})
110+
(version, Failure(errors))
111+
}
112+
}
107113
}
108114
}
109115

@@ -157,8 +163,9 @@ trait BoogieInterface {
157163

158164
/**
159165
* Invoke Boogie.
166+
* Returns None if there was a timeout, otherwise the Boogie output.
160167
*/
161-
private def run(input: String, options: Seq[String]) = {
168+
private def run(input: String, options: Seq[String], timeout: Option[Int]) = {
162169
reporter report BackendSubProcessReport("carbon", boogiePath, BeforeInputSent, _boogieProcessPid)
163170

164171
// When the filename is "stdin.bpl" Boogie reads the program from standard input.
@@ -193,8 +200,15 @@ trait BoogieInterface {
193200
proc.getOutputStream.write(input.getBytes);
194201
proc.getOutputStream.close()
195202

203+
var boogieTimeout = false
204+
196205
try {
197-
proc.waitFor()
206+
timeout match {
207+
case Some(t) if t > 0 =>
208+
boogieTimeout = !proc.waitFor(t, java.util.concurrent.TimeUnit.SECONDS)
209+
case _ =>
210+
proc.waitFor()
211+
}
198212
} finally {
199213
destroyProcessAndItsChildren(proc, boogiePath)
200214
}
@@ -212,7 +226,10 @@ trait BoogieInterface {
212226
val normalOutput = inputConsumer.result.get
213227
reporter report BackendSubProcessReport("carbon", boogiePath, OnExit, _boogieProcessPid)
214228

215-
errorOutput + normalOutput
229+
if (boogieTimeout)
230+
None
231+
else
232+
Some(errorOutput + normalOutput)
216233
} catch {
217234
case _: NoSuchElementException => sys.error("Could not retrieve output from Boogie")
218235
}

0 commit comments

Comments
 (0)