Skip to content

feat(transport): expose pid and process as public properties#819

Open
MukundaKatta wants to merge 1 commit intoanthropics:mainfrom
MukundaKatta:feat/expose-transport-pid-and-process
Open

feat(transport): expose pid and process as public properties#819
MukundaKatta wants to merge 1 commit intoanthropics:mainfrom
MukundaKatta:feat/expose-transport-pid-and-process

Conversation

@MukundaKatta
Copy link
Copy Markdown

Why

anthropics/anthropic-sdk-python#1370 reports that callers using the SDK for cancellation cleanup have to walk async-generator frame internals to reach the underlying subprocess:

```python
def _extract_sdk_pid(gen):
frame = getattr(gen, "ag_frame", None)
for val in frame.f_locals.values():
inner_frame = getattr(val, "ag_frame", None)
transport = inner_frame.f_locals.get("chosen_transport")
proc = getattr(transport, "_process", None)
return proc.pid
```

That's fragile — any rename of private attributes breaks every user of this pattern. Note the issue was filed on `anthropic-sdk-python` but `SubprocessCLITransport` lives here.

What

Two read-only properties on `SubprocessCLITransport`:

  • `pid` → `int | None` — OS process ID (None before connect / after close)
  • `process` → `anyio.abc.Process | None` — the anyio Process handle

Both return None when `self._process is None`, so callers can safely check state without try/except or inspecting private attrs.

What I did not change

The issue also asked for a bounded wait + SIGKILL fallback in `close()`. That's already implemented (see `subprocess_cli.py:481-497` — graceful wait 5s → SIGTERM → wait 5s → SIGKILL). Calling this out so the linked issue can be closed even though not all of its asks translate into code changes.

The issue's third ask (`start_new_session=True`) has Windows portability implications and is out of scope for this minimal change.

Tests

4 new unit tests in `tests/test_transport.py` covering:

  • `pid` returns None before connect()
  • `process` returns None before connect()
  • `pid` returns the subprocess PID when `_process` is set
  • `process` returns the anyio Process handle when set

All 63 existing tests continue to pass.

Related

Closes anthropics/anthropic-sdk-python#1370 (once the issue is migrated here).

Addresses anthropics/anthropic-sdk-python#1370 (filed on the wrong
repo — code lives here).

SubprocessCLITransport spawns a subprocess but exposes no public way to
inspect the process or its PID. Callers needing external cleanup (killpg,
psutil, cgroups) have been walking async-generator frame internals to
reach the underlying Process handle — a workaround that breaks on any
internal refactor.

Adds two read-only properties:

- transport.pid     -> OS process ID, or None before connect()/after close()
- transport.process -> anyio.abc.Process handle, or None

Both return None when no subprocess is running, so callers can safely
check state without try/except.

Note on other asks in #1370:
- Bounded wait + SIGKILL fallback in close() is already implemented
  (see lines 481-497 of subprocess_cli.py).
- start_new_session=True would change cleanup semantics (Windows has
  no POSIX sessions) and is out of scope for this minimal change.

Tests (4 new): pid/process None before connect, pid/process return
expected values when _process is set.

Signed-off-by: Mukunda Katta <mukunda.vjcs6@gmail.com>
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.

Feature request: expose subprocess PID from SubprocessCLITransport for cleanup

1 participant