OPEN RECORD · 5 MEASURED CHECKS
Popen PIPE waiting vs bounded communicate and timeout cleanup
Waiting for a child while both PIPE streams remain unread conflicts with completion for this finite-output fixture. The same child completes after communicate drains its output.
When this evidence is relevant
Investigating subprocess PIPE, Popen wait, communicate timeout: compare the exact failure below with your public error, then check the measured scope.
Observed failure
finite_child_completes_during_selected_wait_strategy
Drain stdout and stderr with communicate. On TimeoutExpired, explicitly kill the direct child and communicate again to drain and reap. Use only bounded output because communicate buffers in memory.
Own synthetic Python child only, shell=False, no network, no descendants. 256 KiB per finite stream, a .25-second observed wait bound, and a separate partial-output sleeper with a 3-second self-exit bound. Same blocked child is drained to completion; timeout alone is not a general deadlock diagnosis. Direct-child cleanup only; no process-tree or unlimited-output claim. Every child has a six-second watchdog exit as an additional bound.
Measured 2026-09-12T13:41:04.198177+00:00 · Linux / x86_64. Historical package versions are not current production recommendations.
Primary references
The complete record and all reproduction files are open. No response is required.
Complete record
- finite_child_completes_during_selected_wait_strategy
- stdout_drained_exactly
- stderr_drained_exactly
- timeout_child_killed_and_reaped_before_return
- partial_stdout_preserved_after_timeout
Full execution record and environments
{
"schema_version": 2,
"test_id": "subprocess-pipe-drain-v1",
"created_at": "2026-09-12T13:41:04.198177+00:00",
"environment": {
"libc": [
"glibc",
"2.39"
],
"machine": "x86_64",
"packages": {},
"python_abi": "cpython-312-x86_64-linux-gnu",
"python_implementation": "CPython",
"python_version": "3.12.14",
"system": "Linux"
},
"fixed_environment": {
"libc": [
"glibc",
"2.39"
],
"machine": "x86_64",
"packages": {},
"python_abi": "cpython-312-x86_64-linux-gnu",
"python_implementation": "CPython",
"python_version": "3.12.14",
"system": "Linux"
},
"status": "passed",
"failure": {
"checks": [
"stdout_drained_exactly",
"stderr_drained_exactly",
"timeout_child_killed_and_reaped_before_return",
"partial_stdout_preserved_after_timeout"
],
"error": "finite_child_completes_during_selected_wait_strategy",
"failed_checks": [
"finite_child_completes_during_selected_wait_strategy"
],
"mode": "broken",
"observations": {
"child_self_exit_bound_seconds": 3,
"finite_output": {
"alive_at_timeout": false,
"guard_child_reaped": true,
"reaped_before_guard": true,
"returncode": 0,
"stderr_bytes": 262144,
"stderr_sha256": "caf546901c2a1966d4530a5a6d0323691f474ee2d6b44286799c440458c7b77f",
"stdout_bytes": 262144,
"stdout_sha256": "4480ce8e19e155ff39079e3379eafd8f369c739e24931ddc684994c2cd12ca91",
"timed_out": true
},
"output_limit_bytes": 524288,
"timeout_child": {
"alive_at_timeout": true,
"guard_child_reaped": true,
"reaped_before_guard": true,
"returncode": -9,
"stderr_bytes": 0,
"stderr_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"stdout_bytes": 11,
"stdout_sha256": "3e5fda43a0585f02a96544ed0cbdf49513d15f25ed2f4370b9fb8f843ddd9317",
"timed_out": true
}
},
"status": "check_failed",
"exit_code": 2
},
"success": {
"checks": [
"finite_child_completes_during_selected_wait_strategy",
"stdout_drained_exactly",
"stderr_drained_exactly",
"timeout_child_killed_and_reaped_before_return",
"partial_stdout_preserved_after_timeout"
],
"error": "",
"failed_checks": [],
"mode": "fixed",
"observations": {
"child_self_exit_bound_seconds": 3,
"finite_output": {
"alive_at_timeout": false,
"guard_child_reaped": true,
"reaped_before_guard": true,
"returncode": 0,
"stderr_bytes": 262144,
"stderr_sha256": "caf546901c2a1966d4530a5a6d0323691f474ee2d6b44286799c440458c7b77f",
"stdout_bytes": 262144,
"stdout_sha256": "4480ce8e19e155ff39079e3379eafd8f369c739e24931ddc684994c2cd12ca91",
"timed_out": false
},
"output_limit_bytes": 524288,
"timeout_child": {
"alive_at_timeout": true,
"guard_child_reaped": true,
"reaped_before_guard": true,
"returncode": -9,
"stderr_bytes": 0,
"stderr_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"stdout_bytes": 11,
"stdout_sha256": "3e5fda43a0585f02a96544ed0cbdf49513d15f25ed2f4370b9fb8f843ddd9317",
"timed_out": true
}
},
"status": "passed",
"exit_code": 0
},
"checks": [
"finite_child_completes_during_selected_wait_strategy",
"stdout_drained_exactly",
"stderr_drained_exactly",
"timeout_child_killed_and_reaped_before_return",
"partial_stdout_preserved_after_timeout"
],
"negative_controls": {
"timeout-only": {
"checks": [
"finite_child_completes_during_selected_wait_strategy",
"stdout_drained_exactly",
"stderr_drained_exactly"
],
"error": "timeout_child_killed_and_reaped_before_return, partial_stdout_preserved_after_timeout",
"failed_checks": [
"timeout_child_killed_and_reaped_before_return",
"partial_stdout_preserved_after_timeout"
],
"mode": "timeout-only",
"observations": {
"child_self_exit_bound_seconds": 3,
"finite_output": {
"alive_at_timeout": false,
"guard_child_reaped": true,
"reaped_before_guard": true,
"returncode": 0,
"stderr_bytes": 262144,
"stderr_sha256": "caf546901c2a1966d4530a5a6d0323691f474ee2d6b44286799c440458c7b77f",
"stdout_bytes": 262144,
"stdout_sha256": "4480ce8e19e155ff39079e3379eafd8f369c739e24931ddc684994c2cd12ca91",
"timed_out": false
},
"output_limit_bytes": 524288,
"timeout_child": {
"alive_at_timeout": true,
"guard_child_reaped": true,
"reaped_before_guard": false,
"returncode": null,
"stderr_bytes": 0,
"stderr_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"stdout_bytes": 0,
"stdout_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"timed_out": true
}
},
"status": "check_failed",
"exit_code": 2
}
},
"test_sha256": "ad0459606e42f61402a605a2412728fbd282775aee43c1666b7b0a692b20aef1",
"fixture_sha256": "89cde701fe6a7e9d5392fc84cb56b969c60c52b4a0dc63401368a6b14e740655",
"requirements_fixed": "# No pip dependencies. CPython 3.11+; measured version in record.json.\n",
"scope": "Own synthetic Python child only, shell=False, no network, no descendants. 256 KiB per finite stream, a .25-second observed wait bound, and a separate partial-output sleeper with a 3-second self-exit bound. Same blocked child is drained to completion; timeout alone is not a general deadlock diagnosis. Direct-child cleanup only; no process-tree or unlimited-output claim. Every child has a six-second watchdog exit as an additional bound.",
"sources": [
{
"title": "Python 3.12 official behavior reference",
"url": "https://docs.python.org/3.12/library/subprocess.html"
}
],
"artifact_sha256": {
"README.md": "5991288edbe50c9b27c1b3a0ebe1a04740be913d041eb30c0f2b5f7cdde00e7d",
"child.py": "04f9de8bc287a99d1ecf0af3126f6bfc85f1dfb0377ff92b537ca23a47043597",
"fixture.json": "89cde701fe6a7e9d5392fc84cb56b969c60c52b4a0dc63401368a6b14e740655",
"pipeline.py": "ad0459606e42f61402a605a2412728fbd282775aee43c1666b7b0a692b20aef1",
"probe.py": "688abd4f4f6ad33173f2c839ca331ff621bb30a0067f74dee62e76c48ce83698",
"requirements-fixed.txt": "c4f1f77998ac5b6df8b96effb120595ce438ddd2b1e25e18943c2e30e2e3c20b",
"runs/broken.stderr.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"runs/broken.stdout.log": "e8580f959409112928caa44eac49c8ce986b290914334712d5dbe8706a400d80",
"runs/fixed.stderr.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"runs/fixed.stdout.log": "d05577ca8aa4f94269302a057a539e0f7f79a6dc38f37e61bbcc50319470caa4",
"runs/probe.stderr.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"runs/probe.stdout.log": "c8557c489211f2c1cdee5f9e06105a01c052552ac0bafe3ca8c62b0ce1d7b5c4",
"runs/timeout-only.stderr.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"runs/timeout-only.stdout.log": "c0faff6bd7c5b0212316946ae91742ce02c5d116506437cda69a07cbf095bc33",
"verification-spec.json": "b08bcbe286378dae22d064f88b263fd667b85f735a9356fef6b3462cc48e414c",
"verify.py": "e3ed969edb6fd4a5cebff0a8af69b948e85c5df52170c54da00054a47aeada7a"
},
"verification": "Actual isolated local subprocess execution; metadata/hash checks excluded from primary workload count.",
"record_id": "295a40dc1c4d26c38af8f2ec8ea97d69e09f61e92a5da0d53842c1d9e3335172"
}Nothing is required in return. Reader notes and result reports are optional.
Optional delivery receipt
All records and downloads are already open. Generate a receipt only if useful for your work.
Responses from readers · unverified
Only notes explicitly authorized for public display appear here. Legacy required responses and new optional notes are distinguished; neither is independent verification.
No public reader responses yet.
Have a complete reproducible solution? Submit it for review →