fix: make SIGALRM-based timeout no-op on Windows for cross-platform support#10
Open
Stevekaplanai wants to merge 1 commit into
Open
fix: make SIGALRM-based timeout no-op on Windows for cross-platform support#10Stevekaplanai wants to merge 1 commit into
Stevekaplanai wants to merge 1 commit into
Conversation
…upport
Windows lacks signal.SIGALRM and signal.ITIMER_REAL, so any attempt to
solve a model from mcp-solver-z3, mcp-solver-pysat, or mcp-solver-maxsat
on Windows currently fails immediately with:
AttributeError: module 'signal' has no attribute 'SIGALRM'
The outer SIGALRM-based timeout is belt-and-suspenders. All three solvers
expose their own internal timeout mechanisms:
- Z3: opt.set('timeout', ms) / solver.set('timeout', ms)
- PySAT: Solver.conf_budget / Solver.prop_budget
- MaxSAT: RC2(timeout=...) plus inherited PySAT budgets
Patched time_limit() in all three environments to detect the absence of
SIGALRM / ITIMER_REAL at runtime and gracefully no-op on Windows. Unix
behavior is unchanged. User code is expected to use the solver-native
timeout knob; the outer wrapper was previously a safety net that broke
the entire Windows install path.
Verified locally on Windows 11 (Python 3.13.13) — both Z3 and MiniZinc
backends now return correct optima on the canonical 3-of-6 picking
problem ('[T,T,F,T,F,F]', objective 27). The patch is also a no-op on
Linux/macOS (hasattr() check passes, full SIGALRM path runs).
Affected files:
- src/mcp_solver/z3/environment.py
- src/mcp_solver/pysat/environment.py
- src/mcp_solver/maxsat/environment.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On Windows, running
mcp-solver-z3,mcp-solver-pysat, ormcp-solver-maxsatfails immediately whensolve_modelis called:Root cause:
time_limit()in each backend'senvironment.pyusessignal.SIGALRMandsignal.setitimer(signal.ITIMER_REAL, ...). Both are Unix-only — Windows'signalmodule doesn't expose them. This makes the entire Windows install path non-functional for these three backends. MiniZinc and ASP backends are unaffected (they use subprocess-based execution).Fix
Patched
time_limit()in all three affectedenvironment.pyfiles to detect the absence ofSIGALRM/ITIMER_REALat runtime viahasattr()and gracefully no-op the outer timeout on Windows. Unix behavior is unchanged.The rationale for no-op (rather than emulating SIGALRM with
threading.Timer):opt.set('timeout', ms)/solver.set('timeout', ms)Solver.conf_budget/Solver.prop_budgetRC2(timeout=...)plus inherited PySAT budgetsthreading.Timercan only set a flag, not preempt running code, so the semantics would diverge silently from the Unix path. Skipping the outer timeout entirely is more honest.time_limit()make this tradeoff explicit and direct users to the solver-native timeout API.Verification
Tested locally on Windows 11 (Python 3.13.13). Before the patch, the Z3 backend errored immediately on any
solve_modelcall. After the patch, the canonical 3-of-6 picking problem solves correctly:Returns
picked: [0, 1, 3](values10 + 8 + 9 = 27), matching what the MiniZinc backend produces for the equivalent model and what the Z3 Python smoke test inINSTALL.mddocuments.The patch is also a no-op on Linux/macOS — the
hasattr()check passes, the full SIGALRM path runs as before. No CI changes required for Unix runners.Files changed
src/mcp_solver/z3/environment.pysrc/mcp_solver/pysat/environment.pysrc/mcp_solver/maxsat/environment.pyNotes for the maintainer
Happy to add a Windows runner to CI if you'd like — would catch this class of regression early. Just say the word and I'll send a follow-up PR.