Skip to content

narrow _monitor_process except to KeyError#770

Open
HrachShah wants to merge 1 commit into
microsoft:mainfrom
HrachShah:fix/jsonrpc-monitor-narrow-exception
Open

narrow _monitor_process except to KeyError#770
HrachShah wants to merge 1 commit into
microsoft:mainfrom
HrachShah:fix/jsonrpc-monitor-narrow-exception

Conversation

@HrachShah

Copy link
Copy Markdown

{"body": "## Summary\n\nReplaces the bare except: clause in ProcessManager._monitor_process (the background thread that waits for a workspace's tool subprocess to exit and then cleans up the registry entries) with a KeyError-only handler.\n\n## Rationale\n\nThe only operations in the try block are:\n\n- del self._processes[workspace] — raises KeyError if the workspace key has already been removed by stop_process or another monitor\n- self._rpc.pop(workspace) — raises KeyError for the same reason\n- rpc.close() — internally wraps every close call in contextlib.suppress(Exception), so it cannot raise\n\nNothing in the block can raise a BaseException subclass that we need to silence other than KeyError. The original bare except: was a try/except-with-no-purpose: a SystemExit or KeyboardInterrupt raised here (extremely unlikely from a del / pop / close call, but conceptually possible if some CPython implementation changed) would have been silently swallowed, which is the wrong default for a thread-pool callback.\n\n## Test plan\n\n- python -m py_compile bundled/tool/lsp_jsonrpc.py passes\n- Lint: pylint bundled/tool/lsp_jsonrpc.py shows no new warnings\n- Manually traceable: each line in the try block has a documented exception type in the Python data model, and KeyError covers all of them\n"}

The bare `except:` in ProcessManager._monitor_process was catching every
exception and silently swallowing it. The only operations inside the try
block are dict del/pop (which raise KeyError) and JsonRpc.close() which
already wraps its operations in `contextlib.suppress(Exception)` and
therefore cannot raise. Replacing the bare except with `except KeyError`
makes the failure mode visible to a future maintainer who introduces a new
call inside the try block that could raise an unrelated exception type.
@HrachShah HrachShah force-pushed the fix/jsonrpc-monitor-narrow-exception branch from 54f288c to d4ec4fa Compare June 23, 2026 23:54

@rchiodo rchiodo left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved via Review Center.

@rchiodo rchiodo left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved via Review Center.

@rchiodo

rchiodo commented Jun 30, 2026

Copy link
Copy Markdown

🔒 Automated review in progress — @rchiodo is auto-reviewing this PR via the Review Center.

Other automated reviewers defer to this claim to avoid duplicate, conflicting feedback. The claim is refreshed while the review is active; if it is not refreshed within the ownership timeout it is treated as vacant and another reviewer may take over. This is an automated marker.

rpc.close()
except: # pylint: disable=bare-except
except KeyError:
# KeyError is sufficient because the process is already dead

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📍 bundled/tool/lsp_jsonrpc.py:185
The comment misstates the cause of the KeyError. The monitor only runs after proc.wait() returns, so the process is always dead at this point — that's not what triggers the KeyError. The KeyError arises because a concurrent path (e.g. stop_process or a restart's monitor) already removed the _processes/_rpc entries. Reword to e.g. # Another path (e.g. stop_process) may have already removed these entries.

@rchiodo rchiodo left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved via Review Center.

@rchiodo

rchiodo commented Jun 30, 2026

Copy link
Copy Markdown

🔒 Automated review in progress — @rchiodo is auto-reviewing this PR via the Review Center.

Other automated reviewers defer to this claim to avoid duplicate, conflicting feedback. The claim is refreshed while the review is active; if it is not refreshed within the ownership timeout it is treated as vacant and another reviewer may take over. This is an automated marker.

@rchiodo

rchiodo commented Jun 30, 2026

Copy link
Copy Markdown

🔒 Automated review in progress — @rchiodo is auto-reviewing this PR via the Review Center.

Other automated reviewers defer to this claim to avoid duplicate, conflicting feedback. The claim is refreshed while the review is active; if it is not refreshed within the ownership timeout it is treated as vacant and another reviewer may take over. This is an automated marker.

@rchiodo

rchiodo commented Jun 30, 2026

Copy link
Copy Markdown

🔒 Automated review in progress — @rchiodo is auto-reviewing this PR via the Review Center.

Other automated reviewers defer to this claim to avoid duplicate, conflicting feedback. The claim is refreshed while the review is active; if it is not refreshed within the ownership timeout it is treated as vacant and another reviewer may take over. This is an automated marker.

@rchiodo

rchiodo commented Jul 1, 2026

Copy link
Copy Markdown

🔒 Automated review in progress — @rchiodo is auto-reviewing this PR.

@rchiodo

rchiodo commented Jul 2, 2026

Copy link
Copy Markdown

🔒 Automated review in progress — @rchiodo is auto-reviewing this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants