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

Add InterruptedExceptions to Model Generation #407

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

baierd
Copy link
Collaborator

@baierd baierd commented Oct 29, 2024

Adds InterruptedExceptions to model generation and catch Z3s solver specific exception when model generation is interrupted and throw a InterruptedException instead.

This adds the exception in quite a lot of places as we have the evaluation connected the model generation.

Also, we can't add the exception to the Iterator class and i threw a RunTimeException instead. We probably want to throw a more precise exception here.

Also, we should check if this is possible in other solvers as well.

…ecific exception when model generation is interrupted and throw a InterruptedExceptions
@PhilippWendler
Copy link
Member

Note that adding a checked exception to a public method is an API-breaking change.

For the Iterator, throwing any exception would be a bug. We don't want the application to crash if Z3 happens to be interrupted at the wrong time (which we often cannot control), no matter whether the crash is due to a Z3Exception or a RuntimeException or something else. The best alternative is likely to set the thread's interrupt status and continue normally.

@kfriedberger
Copy link
Member

I would prefer a solution as in #408 where the InterruptException is handled as RuntimeException. This keeps the signatures cleaner and is compatible with Java-defined interfaces like Iterator.

@baierd
Copy link
Collaborator Author

baierd commented Oct 30, 2024

I completely agree that this solution is ugly and breaking.
I would also prefer something different.

However, i am unsure if we want to throw them as unchecked exceptions for the reasons Philipp pointed out.

I am also unsure if users would expect the interrupt flag of the thread to be set even if we document it, as we have to return something in the methods. And if we return a empty model users might just never notice.

@PhilippWendler
Copy link
Member

Yes, setting the interrupted flag is really only good if the code can continue as it would without the interrupt. Dummy data should never be returned in place of real data.

satisfiableModel = Native.modelEval(z3context, model, formula, false, resultPtr);
} catch (Z3Exception e) {
throw new InterruptedException("Z3 model evaluation was interrupted.");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is wrong. Z3Exceptions can have other causes as well. Please use proper handling from Z3FormulaCreator.handleZ3Exception(e).

return Native.optimizeGetModel(z3context, z3optSolver);
} catch (Z3Exception e) {
throw new InterruptedException("Z3 model generation interrupted.");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is wrong. Z3Exceptions can have other causes as well. Please use proper handling from Z3FormulaCreator.handleZ3Exception(e).

try {
return Native.solverGetModel(z3context, z3solver);
} catch (Z3Exception e) {
throw new InterruptedException("Z3 model generation interrupted.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is wrong. Z3Exceptions can have other causes as well. Please use proper handling from Z3FormulaCreator.handleZ3Exception(e).

Copy link
Member

@kfriedberger kfriedberger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API change is plausible and might be useful for the user.

Please fix the handling of exceptions.

try {
return asList().iterator();
} catch (InterruptedException pE) {
throw new RuntimeException(pE);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to hide the runtime eexception here and just forward the InterruptedException, e.g., without changing the stacktrace and interrupt the exception trace.

@@ -206,7 +208,8 @@ private Collection<ValueAssignment> getConstantArrayAssignment(
* @return a list of assignments {@code a[1]=0; a[2]=0; a[5]=0}.
*/
private Collection<ValueAssignment> getArrayAssignments(
long arraySymbol, long arrayFormula, long value, List<Object> upperIndices) {
long arraySymbol, long arrayFormula, long value, List<Object> upperIndices)
throws InterruptedException {
long evalDecl = Native.getAsArrayFuncDecl(z3context, value);
Native.incRef(z3context, evalDecl);
long interp = Native.modelGetFuncInterp(z3context, model, evalDecl);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the annotations from https://github.com/Z3Prover/z3/blob/master/src/api/java/Model.java , it seems that methods like "modelGetFuncInterp" can also throw a Z3Exception. We might want to check more places for InterruptedException.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Exception when Z3 is interrupted during Model.evaluate()
3 participants