Choose graceful or forced termination inside the existing process helper so
Windows never evaluates the POSIX-only SIGKILL constant. Pass SIGTERM to
pywinpty.kill(), whose native API requires an explicit signal argument.
Keep POSIX process-group TERM-then-KILL escalation and cleanup unchanged.
Cover normal close, forced escalation, kill, and destructor cleanup with a
Windows-shaped process adapter. All 22 focused TTY/pager tests pass, and a
native Windows 11 probe verifies state preservation, destructor termination,
fresh-shell close, and normal asyncio shutdown.
Use nonblocking POSIX PTY reads and buffered, cooperative writes so a full
terminal or stale readiness notification cannot stall other chats. Discard
a shell on cancellation only while command bytes remain unsent, preserving
shell state after a fully drained send.
Use best-effort synchronous destruction instead of reentering asyncio;
explicit close retains the existing awaited cleanup and signal escalation.
Add isolated regression checks for payload integrity, loop responsiveness,
partial and complete-send cancellation, descriptor reuse, cross-thread
cleanup, and destruction. Document the terminal lifecycle contracts.
Validation: 28 focused terminal, parallel-lifetime, and pager tests passed.
Four real Codex II chats also completed concurrent Linux terminal, Python,
and Node workloads with 29.87 seconds of overlap and intact shell state.
Detect and treat terminated local/SSH/TTY shells as definitive command completion. Add is_terminated and get_exit_code helpers to LocalInteractiveSession, SSHInteractiveSession, and TTYSession; expand _is_closed_pty_error to recognize exited TTY processes. CodeExecution now reports a shell-exit prompt, recreates terminated sessions lazily before the next command, and returns immediately when a shell has exited. Docs and README updated to describe strict-mode/exit behavior, and tests were added/updated to cover the new termination detection and handling.
Start local PTY shells in a new process session and make close() escalate from SIGTERM to SIGKILL when a foreground command refuses to exit. This keeps code_execution_tool reset from blocking indefinitely on stuck terminal processes.\n\nAdd regression coverage for closing a TERM-resistant shell and document the reset lifecycle contract.
Guard stream reconfiguration so pytest capture objects without reconfigure support can import the code execution TTY helper while preserving UTF-8 error handling for normal streams.
Use a shared mutable holder for the POSIX PTY master fd and invalidate it before close. This keeps EOF cleanup and TTYSession.close()/kill() idempotent and prevents closing an unrelated resource if the OS reuses the old fd number.
Detect closed or exited local TTY sessions before writing, convert invalid PTY write errors into retryable session failures, and reset/retry the terminal session once after send/read failures.
Store and close POSIX PTY master descriptors when terminal sessions are closed or killed, and make local terminal session shutdown await the full TTY cleanup path. This prevents leaked /dev/ptmx descriptors from exhausting the process file descriptor limit.