Closed
Labels
3.11only security fixesonly security fixes3.12only security fixesonly security fixestopic-asynciotype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Description
| BPO | 43884 |
|---|---|
| Nosy | @asvetlov, @1st1, @sweeneyde, @kumaraditya303, @skeggse |
| PRs | |
| Files |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee = None
closed_at = None
created_at = <Date 2021-04-19.02:47:38.245>
labels = ['3.11', 'type-bug', 'expert-asyncio']
title = 'Cannot cleanly kill a subprocess using high-level asyncio APIs'
updated_at = <Date 2022-03-23.09:08:45.631>
user = 'https://bugs.python.org/rabraham'bugs.python.org fields:
activity = <Date 2022-03-23.09:08:45.631>
actor = 'kumaraditya'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['asyncio']
creation = <Date 2021-04-19.02:47:38.245>
creator = 'rabraham'
dependencies = []
files = ['49965']
hgrepos = []
issue_num = 43884
keywords = ['patch']
message_count = 6.0
messages = ['391349', '391350', '391369', '391379', '399937', '415859']
nosy_count = 6.0
nosy_names = ['asvetlov', 'yselivanov', 'rabraham', 'Dennis Sweeney', 'kumaraditya', 'skeggse']
pr_nums = ['31611', '32073']
priority = 'normal'
resolution = None
stage = 'patch review'
status = 'open'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue43884'
versions = ['Python 3.11']Metadata
Metadata
Assignees
Labels
3.11only security fixesonly security fixes3.12only security fixesonly security fixestopic-asynciotype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Projects
- StatusShow more project fieldsDone
Activity
rabraham commentedon Apr 19, 2021
There doesn't appear to be a way to prematurely kill a subprocess using the high-level asyncio subprocess APIs (https://docs.python.org/3.9/library/asyncio-subprocess.html) without getting a traceback on exit.
On exit, the attached program writes the following to stderr:
Exception ignored in: <function BaseSubprocessTransport.__del__ at 0x1065f0dc0> Traceback (most recent call last): ... raise RuntimeError('Event loop is closed') RuntimeError: Event loop is closedIf I uncomment
# process._transport.close()or commentasyncio.sleep(1), the walkback disappears. (I get the same behavior in python 3.8. I haven't tried other python versions.)rabraham commentedon Apr 19, 2021
Reproducing the program here:
Can I use the high-level API to kill a subprocess cleanly without having to access the protected member process._transport? Seems like an oversight perhaps?
sweeneyde commentedon Apr 19, 2021
Running kill_subprocess.py on Windows 10, I get these results:
Python 3.7.2 (tags/v3.7.2:9a3ffc0492)
- raises NotImplementedError in base_events.py, _make_subprocess_transport
Python 3.8.2 (tags/v3.8.2:7b3ab59)
- Success
Python 3.9.0 (tags/v3.9.0:9cf6752)
- Success
Python 3.10.0a6 (tags/v3.10.0a6:cc12888)
- Success
What is your OS?
rabraham commentedon Apr 19, 2021
I see this on MacOS and Linux, but I suspect any Unix-like system would have the same behavior.
skeggse commentedon Aug 19, 2021
I'm also experiencing this, with virtually identical code, on macOS 10.15.7. The given fix (process._transport.close()) also works for me, so I'm just using that workaround for the time being.
25 remaining items
pythonGH-88050: fix race in closing subprocess pipe in asyncio (pytho…
[3.11] GH-88050: fix race in closing subprocess pipe in asyncio (GH-9…
Merge branch 'main' into typewatch
pythongh-88050: Fix asyncio subprocess to kill process cleanly when p…
pythonGH-88050: fix race in closing subprocess pipe in asyncio (pytho…
theo-brown commentedon Feb 2, 2023
Is this meant to be fixed in 3.11+?
gvanrossum commentedon Feb 2, 2023
Yes
theo-brown commentedon Feb 2, 2023
Which patch? Not in 3.11.0 as far as I can tell.
gvanrossum commentedon Feb 2, 2023
#32073 and a followup are present in 3.11.1. They may not be present in 3.11.0.
gertvdijk commentedon Apr 2, 2023
Hmm. I came here using Google while I'm on 3.11.2 already. This happens sometimes for me on a subprocess wrapped inside a task and stdin/stderr connected. It also only triggers when I am terminating a process myself, instead killing it or letting the loop killing it.
Found this when hitting random test failures on 3.11.2 and created the minimal reproducer below.
Running this in a shell loop 200 times, this gives ~ 1-10 failures per loop, looks random.
Either removing
proc.terminate()or replacing it withproc.kill()makes the traceback disappear. 🤷🏼Also notice the (unrelated) error:
Further relevant system info:
Python 3.11.2 (main, Mar 27 2023, 01:01:40) [GCC 12.2.1 20230201], built using Pyenv on Linux 6.2.9 (Arch, x86_64).Am I doing something wrong here or hitting a corner case that's not tackled by this bugfix? Thanks! 🙏🏼
kumaraditya303 commentedon Apr 3, 2023
You are missing
await proc.wait()after terminating the process, adding that fixes it. Anyways this is not related to this fix so create a new issue if you still face the issue.gertvdijk commentedon Apr 3, 2023
Are you sure I should? It's also not included in Here’s an example of how asyncio can run a shell command and obtain its result, here: https://docs.python.org/3/library/asyncio-subprocess.html#
Note that I'm already awaiting the process result with
communicate(). Forwait()this comment (here) seems to indicate that as well I shouldn't:Sorry for the noise then, but to me it sounds exactly the same still.
kumaraditya303 commentedon Apr 3, 2023
You are wrapping
proc.communicate()inwait_forso it gets cancelled before it had to chance to callself.wait(). See the source code. The docs are for directly awaiting theproc.communicate()which doesn't work in case ofwait_for.fix: Suppress Linux asyncio cleanup warning (documented)
fix: Suppress Linux asyncio cleanup warning (documented)