proof-solvers: a time limit on every z3 goal, and a deadline on its I/O #239

Merged
dcharlot merged 1 commit from fix/z3-goal-deadline into main 2026-10-13 09:32:22 -04:00

2026-10-13

Transaction Science
proof-solvers: a time limit on every z3 goal, and a deadline on its I/O
All checks were successful
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 2m35s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 1m30s
standards workspaces build + test / aac-rs (pull_request) Successful in 2m34s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 56s
standards workspaces build + test / map-rs (pull_request) Successful in 55s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 51s
standards workspaces build + test / mesh-rs (pull_request) Successful in 55s
standards workspaces build + test / openpay (pull_request) Successful in 3m10s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 4m45s
lockfiles / every Cargo.lock is current (pull_request) Successful in 44s
standards workspaces build + test / arl-rs (pull_request) Successful in 1m9s
standards workspaces build + test / eoc-rs (pull_request) Successful in 2m5s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m37s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 1m9s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 1m11s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m29s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m22s
standards workspaces build + test / sense-rs (pull_request) Successful in 1m14s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 4m5s
The resident z3 session had no limit. One goal z3 could not decide held the
session, and every goal queued behind it, for as long as z3 kept at it.

Two guards now close that, in the resident session and the one-shot z3 alike:

- z3's own soft limit (`-t:`, GOAL_TIMEOUT = 60 s by default;
  Z3Server::with_goal_timeout). At the limit `(check-sat)` answers
  `unknown`, which counts as undecided, and the session decides on.
- A deadline GOAL_DEADLINE_GRACE (5 s) past that limit, on both the write
  and the read. A goal can lift z3's limit for itself with
  `(set-option :timeout ...)`. Past the deadline the one-shot z3 is killed,
  and the resident session is broken and replaced.

z3 reads its input only as it reaches each command. So a goal with a
`(check-sat)` of its own and more than a pipe's worth of text after it
blocked the write on the calling thread for as long as that check ran.
Both ends of the pipe are now on threads of their own.

Checked on Homebrew z3 (build host) and on Ubuntu's 4.8.12 (the CI
image's version): unknown at the soft limit, the limit lifted by a goal's
:timeout even after (reset), and a 426 KB write that blocks behind the
goal's own check.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 03:02:17 -04:00