-
-
Notifications
You must be signed in to change notification settings - Fork 371
Description
As a simplified example, I would like to:
- start a shell command
- wait some time
- stop it
The problem is that a child subprocesses from the shell won't terminate on cancel and would keep running even after python process is finished.
The problem is present only when a command consists of several processes, like ping localhost | cat, but not when a command is simple, like sleep 20.
Tested with: ubuntu-24.04, python 3.12.8, trio 0.29.0
Steps to reproduce:
- check for currently running
pingprocesses:ps aux | grep ping(confirm nopingprocess is running) - run the test script (see below)
python ./test.py - check list of processes again, while the test script is running and after the test script terminates
Expected result is that a shell + ping + cat are all running only for 5 seconds.
Actual result that a shell process is running for 5 seconds, but the ping and also cat processes remain running not just beyond 5 seconds, but even after a script terminates. It looks like the subprocesses get detached from the shell and are not considered childs any more. I am not sure if this is 1 or 2 separate problems. I am not even sure if this is a proper way to run a shell script from within trio.
In any case, is there a workaround or a better way to run shell commands?
test.py script:
import trio
from subprocess import DEVNULL
# cmd = 'sleep 20' # this is properly stopped
cmd = 'ping localhost | cat' # this command won't stop properly
async def test():
async with trio.open_nursery() as ns:
async def service_runner(task_status = trio.TASK_STATUS_IGNORED):
with trio.CancelScope() as scope:
task_status.started(scope)
await trio.run_process(cmd, shell=True, check=False,
stdout=DEVNULL, stderr=DEVNULL)
ns.cancel_scope.cancel()
service_scope = await ns.start(service_runner)
await trio.sleep(5.0)
service_scope.cancel()
await trio.sleep(5.0)
trio.run(test)