-
Notifications
You must be signed in to change notification settings - Fork 3
fix: Use daemon threads for SolverManager #69
fix: Use daemon threads for SolverManager #69
Conversation
Before, if a SolverManager creates a Solver, it creates a non-daemon thread, which can prevent the Python process from EVER exiting unless forced. Now, the SolverManager spawns only daemon threads, which allows the Python process to exit. This also allows us to remove some test configuration code that was used to force the JVM to exit. Additionaly, SolverManager can take SolverConfig directly and may take a SolutionManagerConfig too.
- Tests were flaky before, since the problem fact change may affect the input problem if the change was applied before solving was started.
- Might fix the flakiness
Maybe finally a fix for flakiness?
Seem to have an effect?
Less SolverManagers => less flakyness
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not entirely sure about the daemon threads.
Why should the process terminate if the solver jobs haven't? The jobs are important payload. To me, this doesn't sound like the least surprising behavior.
More importantly - what does the Java solver do? Does it also create deamon threads? If not, then for consistency, neither should the Python solver.
I understand the Python
|
Yes, but I'm asking something else. Forget Python Solver. What's the default behavior of the Java solver, without any fancy configuration? My argument is that the Python solver's default behavior should be exactly the same. (In other words: if the Java solver by default doesn't do daemon threads, neither should the Python solver.) |
If you control-C the Java solver and don't configure a signal handler, Java terminates without daemon threads. |
Which is a problem that should be solved by properly shutting down the executor when no longer needed, no? |
Nope; that was done in tests, and tests also hang and needed specially handling code |
In my opinion, the key here is to figure out why does Java terminate in one case, and not in the other. Solving that through daemon threads is IMOM a hack, and not a solution - there will be a root cause there somewhere. |
Because Python hold a reference and a ThreadPoolExecutor keeps it threads alive once spawn, creating a catch-22:
|
And Python cannot shut down the executor and drop the reference? In Java, you'd set the field to |
Nope; consider user experience; "Why isn't my program terminating? Why is my test hanging?" That is terrible UX. solver_manger = SolverManager.create(solver_config)
@app.get("/root/solve")
async def solve(timetable: Timetable) :
solver_manager.solve('ID', timetable, ...) And users do not want that code to hang on Control-C |
I fully agree with that. It just seems logical that a framework that does this (see Daemon threads are a solution to the problem which we may need to accept, but the real solution would be to somehow free the resources we've taken and allow a clean shutdown on its own. |
That the responsibility of JPype, which adds its own shutdown hook to Python, which hangs forever w/o daemon threads. |
timefold-solver-python-core/src/main/java/ai/timefold/solver/python/DaemonThreadFactory.java
Show resolved
Hide resolved
|
timefold-solver-python-core/src/main/java/ai/timefold/solver/python/DaemonThreadFactory.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
Before, if a
SolverManager
creates aSolver
, it createsa non-daemon thread, which can prevent the Python process from
EVER exiting unless forced.
Now, the
SolverManager
spawns only daemon threads, which allows thePython process to exit. This also allows us to remove some test
configuration code that was used to force the JVM to exit.
Additionally,
SolverManager
can takeSolverConfig
directly and maytake a
SolutionManagerConfig
too.Tests were flaky before, since the problem fact change may affect
the input problem if the change was applied before solving was
started.