create_subprocess with set_event_loop(None) can't interact with child process producing zombies
Don't know how legit is that to set_event_loop(None). Discovered this issue making testing suite, where I create new_event_loop for each test. This thing is unobvious.
import asyncio
command = ('ls', '-l')
@asyncio.coroutine
def run_process(loop):
proc = yield from asyncio.create_subprocess_exec(
*command,
loop=loop
)
yield from proc.wait()
print(proc.returncode)
@asyncio.coroutine
def main(loop):
yield from run_process(loop)
loop = asyncio.new_event_loop()
asyncio.set_event_loop(None) # makes wait() infinite, returncode always None
# asyncio.set_event_loop(loop) # this fixes
try:
loop.run_until_complete(main(loop))
finally:
loop.close()
Oh, the "child watcher" part of subprocesses is nearly not documented in asyncio :-/ With your example, the child watcher never runs. You have to configure it explicitly with:
asyncio.get_child_watcher().attach_loop(loop)
The doc is probably restricted to short sentence mentionning vaguely child watchers...
https://docs.python.org/dev/library/asyncio-subprocess.html#asyncio-subprocess-threads
We need to document better the implementation. The problem is that child watchers are specific to UNIX (not available on Windows).
Shouldn't create_subprocess_exec() and other related functions ensure that the ChildWatcher is working for the loop used during process creation (the one given in parameter or the default one)?
It seems that ChildWatcher is not supposed to be exposed to users.
Unfortunately you have to manage the child watcher when you choose to create multiple event loops that spawn subprocesses. There's definitely some unfinished business here that I'd like to see fixed before 3.6 rolls around. Some help would be appreciated!