Audit CPLEX license-slot leaks
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 257
- Forks
- 87
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 29
Description
Follow-up from #695 (the broader audit triggered by #679).
After fixing the Mosek/COPT/MindOpt probe and _run_file leaks, two solvers remain unaudited because they have no explicit cleanup and rely on the wrapper's __del__:
CPLEX
In Cplex._run_file (linopy/solvers.py:1765):
m = cplex.Cplex()
...
return self._make_result(status, solution, solver_model=m)
m is stored as solver_model and is only ever cleared by Solver.close() setting it to None. The Cplex Python API recommends an explicit m.end() to release the model and the underlying license slot. Whether dropping the reference reliably calls end() via __del__ is library-internal — needs verification with a real CPLEX license.~
(xpress already covered, unfold to see original xpress section)
Xpress
In Xpress._run_file (linopy/solvers.py:2213) and Xpress._build_direct (linopy/solvers.py:2032):
m = xpress.problem()
m.read(...)
...
return self._solve(m, ...)
Same shape — m is the license-bearing object, stored as solver_model, no explicit m.reset() / equivalent.
Suggested approach
- Register cleanup on
_env_stack(e.g.self._env_stack.callback(m.end)for CPLEX) soclose()releases the slot deterministically. - Verify with a real license that calling
end()is idempotent and doesn't break the result accessors that other tests rely on.
Why this wasn't in #695
I don't have CPLEX or Xpress licensed locally and didn't want to ship a "fix" that only works in theory and might break working solver paths in CI. Tagging this so anyone with a CPLEX/Xpress license can pick it up.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in linopy/solvers.py at Cplex._run_file (around line 1765), Xpress._run_file (around line 2213), and Xpress._build_direct (around line 2032), then inspect Solver.close() and _env_stack handling. Verify explicit cleanup with real CPLEX or Xpress licenses, confirm it is idempotent, and ensure result accessors and existing solver paths still work.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100