Fix analysis engine receiving bare 'go' instead of 'go infinite'#63
Merged
Fix analysis engine receiving bare 'go' instead of 'go infinite'#63
Conversation
When analysis is running and the user presses navigation buttons rapidly, stop the analysis immediately but defer restarting it until 300ms after the last button press. This avoids repeated blocking engine stop/start cycles that make the GUI unresponsive. Agent-Logs-Url: https://github.com/fsmosca/Python-Easy-Chess-GUI/sessions/71d680e7-f5da-483b-86f3-c7daf8a96f24 Co-authored-by: fsmosca <22366935+fsmosca@users.noreply.github.com>
Replace blocking stop_review_analysis() on navigation press with non-blocking search.stop() signal. The join+restart is deferred to the debounce handler which fires 300ms after the last button press, by which time the old thread has already exited. Also skip stale analysis messages from the old position during debounce to prevent incorrect UI updates. Agent-Logs-Url: https://github.com/fsmosca/Python-Easy-Chess-GUI/sessions/0e57255b-5a2d-4189-9dc6-ce5b07d5f43f Co-authored-by: fsmosca <22366935+fsmosca@users.noreply.github.com>
When the analysis thread is interrupted via _kill.set(), if no bestmove was found yet (bm is None), RunEngine.run() falls through to engine.play(board, Limit(depth=None)) — an unconstrained synchronous call that blocks the thread indefinitely. This makes join() hang and freezes the GUI. Fix: skip the engine.play() fallback when _kill is set, and also make the move delay loop respect the kill signal. Agent-Logs-Url: https://github.com/fsmosca/Python-Easy-Chess-GUI/sessions/225e88fb-0a7d-479d-8208-22d1eb8867e0 Co-authored-by: fsmosca <22366935+fsmosca@users.noreply.github.com>
python-chess's engine.analysis() checks `if limit:` to decide whether to send 'go infinite'. Since Limit() with all-None fields is a truthy dataclass instance, passing Limit(depth=None) caused python-chess to send bare 'go' without the 'infinite' token. The engine received 'go' with no parameters and sat idle. Fix: pass limit=None (not Limit()) for tc_type='infinite' with no depth constraint, so python-chess takes the else branch and sends 'go infinite'. Also guard the engine.play() fallback against limit=None. Agent-Logs-Url: https://github.com/fsmosca/Python-Easy-Chess-GUI/sessions/d96d5ff9-9d28-43b2-bd39-3600dbd677ec Co-authored-by: fsmosca <22366935+fsmosca@users.noreply.github.com>
Copilot created this pull request from a session on behalf of
fsmosca
March 29, 2026 04:01
View session
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.
Review mode analysis engine sits idle because it receives the UCI command
go(no parameters) instead ofgo infinite. The board never updates and the GUI becomes unresponsive.Root cause
python-chess's
engine.analysis(board, limit)decides whether to appendinfiniteviaif limit:. ALimit()dataclass with all-Nonefields is truthy, so passingLimit(depth=None)produces baregoinstead ofgo infinite:Changes
limit=Nonefor infinite analysis — Whentc_type='infinite'with no depth constraint, passNoneinstead ofLimit(depth=None)so python-chess takes theelsebranch and sendsgo infinite. Custom depth limits still useLimit(depth=X)→go depth X.Guard
engine.play()fallback againstNonelimit — The bestmove fallback path now also checkslimit is not Noneto avoid passingNonetoengine.play().Skip
engine.play()fallback when killed (prior commit) — After_kill.set(),RunEngine.run()was falling through toengine.play(board, Limit(depth=None))which blocked the thread indefinitely. Now skipped when the kill signal is set.Non-blocking review navigation with debounce (prior commit) — Navigation signals the analysis thread to stop without blocking on
join(). The actual restart is deferred via a 300ms debounce in the timeout handler, keeping the GUI responsive during rapid navigation.