Closes the asyncio subprocess transport, if there is one. The transport otherwise stays open (and warns at GC) while a surviving descendant holds a pipe end; nothing public exposes it, hence the attribute walk. No-op on trio and the Windows fallback.
(process: ServerProcess)
| 302 | |
| 303 | |
| 304 | def _close_subprocess_transport(process: ServerProcess) -> None: |
| 305 | """Closes the asyncio subprocess transport, if there is one. |
| 306 | |
| 307 | The transport otherwise stays open (and warns at GC) while a surviving |
| 308 | descendant holds a pipe end; nothing public exposes it, hence the attribute |
| 309 | walk. No-op on trio and the Windows fallback. |
| 310 | """ |
| 311 | transport = getattr(getattr(process, "_process", None), "_transport", None) |
| 312 | # Duck-typed: uvloop's UVProcessTransport is not an asyncio.SubprocessTransport. |
| 313 | close = getattr(transport, "close", None) |
| 314 | if callable(close): |
| 315 | # close() on <=3.12 can raise PermissionError re-killing a setuid child. |
| 316 | with suppress(PermissionError): |
| 317 | close() |
| 318 | |
| 319 | |
| 320 | def _get_executable_command(command: str) -> str: |
no test coverage detected