Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Cancellation tokens to cancel and restart checkers #497

Merged
merged 22 commits into from
Feb 14, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e4d2c11
Enable cancelling in SplitAndVerifyWorker
keyboardDrummer Feb 9, 2022
d120ed0
Push cancellationToken down into SMTLibProcessTheoremProver
keyboardDrummer Feb 10, 2022
5ebf252
Push CancellationToken into SMTLibProcess
keyboardDrummer Feb 10, 2022
cef3205
Kill process if it doesn't become idle
keyboardDrummer Feb 10, 2022
cbecd05
Checker waiters can continue with a fresh new checker.
MikaelMayer Feb 10, 2022
8b3f264
Add test
keyboardDrummer Feb 11, 2022
5df1ae2
Merge branch 'cancellationToken2' of github.com:keyboardDrummer/boogi…
keyboardDrummer Feb 11, 2022
d12b905
Revert "Checker waiters can continue with a fresh new checker."
keyboardDrummer Feb 11, 2022
5ed982b
Stop Checker.WaitForOutput correctly from swallowing OperationCancell…
keyboardDrummer Feb 11, 2022
efe44ee
Correctly handle dead checkers
keyboardDrummer Feb 11, 2022
88be748
Record a cancelled pipeline outcome
keyboardDrummer Feb 11, 2022
3320ffb
Use log variable
keyboardDrummer Feb 11, 2022
e003b78
Refactoring and allow checkers to be recycled
keyboardDrummer Feb 11, 2022
ccdfd34
Let SMTLibProcess wait for the solver using a TaskCompletionSource, a…
keyboardDrummer Feb 11, 2022
6dac526
Shorten test program
keyboardDrummer Feb 11, 2022
71144bc
Small tweaks
keyboardDrummer Feb 11, 2022
5e3111f
Fix rename feature
keyboardDrummer Feb 11, 2022
7a30748
Fix off by one error
keyboardDrummer Feb 11, 2022
2f1c0b5
Refactoring
keyboardDrummer Feb 11, 2022
840d12d
Make sure we don't run into issues with an aggregateException
keyboardDrummer Feb 11, 2022
c926f8f
Refactoring to remove code duplication
MikaelMayer Feb 11, 2022
7014ead
Merge branch 'cancellationToken2' of github.com:keyboardDrummer/boogi…
MikaelMayer Feb 11, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Source/ExecutionEngine/ExecutionEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1207,9 +1207,9 @@ private static void VerifyImplementation(Program program, PipelineStatistics sta
CommandLineOptions.Clo.XmlSink.WriteStartMethod(impl.Name, verificationResult.Start);
}

try
{
verificationResult.Outcome = vcgen.VerifyImplementation(impl, out verificationResult.Errors, requestId);
try {
var cancellationToken = RequestIdToCancellationTokenSource[requestId].Token;
verificationResult.Outcome = vcgen.VerifyImplementation(impl, out verificationResult.Errors, requestId, cancellationToken);
if (CommandLineOptions.Clo.ExtractLoops && verificationResult.Errors != null)
{
var vcg = vcgen as VCGen;
Expand Down
14 changes: 7 additions & 7 deletions Source/Houdini/Checker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Microsoft.BaseTypes;
using VC;
using System.Linq;
using System.Threading;

namespace Microsoft.Boogie.Houdini
{
Expand Down Expand Up @@ -256,7 +257,7 @@ public ProverInterface.Outcome Verify(ProverInterface proverInterface, Dictionar

VCExpr vc = proverInterface.VCExprGen.Implies(BuildAxiom(proverInterface, assignment), conjecture);
proverInterface.BeginCheck(descriptiveName, vc, handler);
ProverInterface.Outcome proverOutcome = proverInterface.CheckOutcome(handler, errorLimit);
ProverInterface.Outcome proverOutcome = proverInterface.CheckOutcome(handler, errorLimit, CancellationToken.None).Result;

double queryTime = (DateTime.UtcNow - now).TotalSeconds;
stats.proverTime += queryTime;
Expand Down Expand Up @@ -388,8 +389,8 @@ public void Explain(ProverInterface proverInterface,
do
{
hardAssumptions.Add(controlExprNoop);
outcome = proverInterface.CheckAssumptions(hardAssumptions, softAssumptions, out var unsatisfiedSoftAssumptions,
handler);
(outcome, var unsatisfiedSoftAssumptions) = proverInterface.CheckAssumptions(hardAssumptions, softAssumptions,
handler, CancellationToken.None).Result;
hardAssumptions.RemoveAt(hardAssumptions.Count - 1);

if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory ||
Expand Down Expand Up @@ -423,9 +424,8 @@ public void Explain(ProverInterface proverInterface,
hardAssumptions.Add(softAssumptions[i]);
}

var unsatisfiedSoftAssumptions2 = new List<int>();
outcome = proverInterface.CheckAssumptions(hardAssumptions, softAssumptions2, out unsatisfiedSoftAssumptions2,
handler);
(outcome, var unsatisfiedSoftAssumptions2) = proverInterface.CheckAssumptions(hardAssumptions, softAssumptions2,
handler, CancellationToken.None).Result;

if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory ||
outcome == ProverInterface.Outcome.OutOfResource || outcome == ProverInterface.Outcome.Undetermined)
Expand Down Expand Up @@ -506,7 +506,7 @@ public void UpdateUnsatCore(ProverInterface proverInterface, Dictionary<Variable
assumptionExprs.Add(exprTranslator.LookupVariable(v));
}

ProverInterface.Outcome tmp = proverInterface.CheckAssumptions(assumptionExprs, out var unsatCore, handler);
(ProverInterface.Outcome tmp, var unsatCore) = proverInterface.CheckAssumptions(assumptionExprs, handler, CancellationToken.None).Result;
System.Diagnostics.Debug.Assert(tmp == ProverInterface.Outcome.Valid);
unsatCoreSet = new HashSet<Variable>();
foreach (int i in unsatCore)
Expand Down
6 changes: 4 additions & 2 deletions Source/Provers/SMTLib/NoopSolver.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.Boogie.SMTLib;

Expand Down Expand Up @@ -34,11 +36,11 @@ public override void Send(string cmd)
}
}

public override SExpr GetProverResponse()
public override Task<SExpr> GetProverResponse(CancellationToken cancellationToken)
{
var result = response;
response = null;
return result;
return Task.FromResult(result);
}

public override void NewProblem(string descriptiveName)
Expand Down
151 changes: 67 additions & 84 deletions Source/Provers/SMTLib/SMTLibProcess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.IO;
using System.Threading;
using System.Diagnostics.Contracts;
using System.Threading.Tasks;

namespace Microsoft.Boogie.SMTLib
{
Expand Down Expand Up @@ -118,82 +119,67 @@ internal Inspector Inspector
get { return inspector; }
}

public override SExpr GetProverResponse()
public override Task<SExpr> GetProverResponse(CancellationToken cancellationToken)
{
toProver.Flush();
return Task.Factory.StartNew(GetProverResponseSync, cancellationToken);
}

while (true)
{
var exprs = ParseSExprs(true).ToArray();
Contract.Assert(exprs.Length <= 1);
if (exprs.Length == 0)
{
return null;
}
private SExpr GetProverResponseSync()
{
toProver.Flush();

var resp = exprs[0];
if (resp.Name == "error")
{
if (resp.Arguments.Length == 1 && resp.Arguments[0].IsId)
{
if (resp.Arguments[0].Name.Contains("max. resource limit exceeded"))
{
return resp;
}
else {
HandleError(resp.Arguments[0].Name);
return null;
}
}
else {
HandleError(resp.ToString());
lock (this) {
while (true) {
var exprs = ParseSExprs(true).ToArray();
Contract.Assert(exprs.Length <= 1);
if (exprs.Length == 0) {
return null;
}
}
else if (resp.Name == "progress")
{
if (inspector != null)
{
var sb = new StringBuilder();
foreach (var a in resp.Arguments)
{
if (a.Name == "labels")
{
sb.Append("STATS LABELS");
foreach (var x in a.Arguments)
{
sb.Append(" ").Append(x.Name);
}

var resp = exprs[0];
if (resp.Name == "error") {
if (resp.Arguments.Length == 1 && resp.Arguments[0].IsId) {
if (resp.Arguments[0].Name.Contains("max. resource limit exceeded")) {
return resp;
} else {
keyboardDrummer marked this conversation as resolved.
Show resolved Hide resolved
HandleError(resp.Arguments[0].Name);
return null;
}
else if (a.Name.StartsWith(":"))
{
sb.Append("STATS NAMED_VALUES ").Append(a.Name);
foreach (var x in a.Arguments)
{
sb.Append(" ").Append(x.Name);
} else {
HandleError(resp.ToString());
return null;
}
} else if (resp.Name == "progress") {
if (inspector != null) {
var sb = new StringBuilder();
foreach (var a in resp.Arguments) {
if (a.Name == "labels") {
sb.Append("STATS LABELS");
foreach (var x in a.Arguments) {
sb.Append(" ").Append(x.Name);
}
} else if (a.Name.StartsWith(":")) {
sb.Append("STATS NAMED_VALUES ").Append(a.Name);
foreach (var x in a.Arguments) {
sb.Append(" ").Append(x.Name);
}
} else {
continue;
}
}
else
{
continue;
}

inspector.StatsLine(sb.ToString());
sb.Clear();
inspector.StatsLine(sb.ToString());
sb.Clear();
}
}
} else if (resp.Name == "unsupported") {
// Skip -- this may be a benign "unsupported" from a previous command.
// Of course, this is suboptimal. We should really be using
// print-success to identify the errant command and determine whether
// the response is benign.
} else {
return resp;
}
}
else if (resp.Name == "unsupported")
{
// Skip -- this may be a benign "unsupported" from a previous command.
// Of course, this is suboptimal. We should really be using
// print-success to identify the errant command and determine whether
// the response is benign.
}
else
{
return resp;
}
}
}

Expand Down Expand Up @@ -428,29 +414,26 @@ string ReadProver()
error = null;
}

lock (this)
while (proverOutput.Count == 0 && proverErrors.Count == 0 && !prover.HasExited)
{
while (proverOutput.Count == 0 && proverErrors.Count == 0 && !prover.HasExited)
{
Monitor.Wait(this, 100);
}
Monitor.Wait(this, 100);
}

if (proverErrors.Count > 0)
{
error = proverErrors.Dequeue();
continue;
}
if (proverErrors.Count > 0)
{
error = proverErrors.Dequeue();
continue;
}

if (proverOutput.Count > 0)
{
return proverOutput.Dequeue();
}
if (proverOutput.Count > 0)
{
return proverOutput.Dequeue();
}

if (prover.HasExited)
{
DisposeProver();
return null;
}
if (prover.HasExited)
{
DisposeProver();
return null;
}
}
}
Expand Down
Loading