-
Notifications
You must be signed in to change notification settings - Fork 553
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Blocking loop.subprocess_shell() and loop.subprocess_exec() #118
Comments
Yes. Will take a look in a week or two. If you have time to make a PR I'll review it. |
Actually, uvloop can block only if you supply a |
Sorry I wasn't following up this old issue. |
We have a component in Home Assistant; they call ffmpeg with a subprocess (async). They also end sometimes (less and more) in blocking and not working event loop :( I can't provide any test code because it's not all time simple to reproduce it in a laboratory situation. The point is, we don't use |
The problem is forking. It looks like the current implementation doesn't work on a heavy load of the main process. |
IIRC, the call to fork() can be slow because of the internals of the memory
management (I think it's in O(n) with the number of memory pages of the
forked process).
Usually the workaround is to use vfork() when knowing that exec() will be
called right after, but I don't think that this option is safe in Python.
I think that the problem is more about a blocking IPC used to synchronize
the parent and the child to transmit failures in preexec_fn. I made a PR
that got lost for cpython with vanilla asyncio years ago for this problem:
python/asyncio#428
Cheers
Le jeu. 25 avr. 2019 à 21:46, Pascal Vizeli <[email protected]> a
écrit :
… The problem is forking. It looks like the current implementation doesn't
work on a heavy load of the main process.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#118 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AABPWGGLH3YZJGF6VZRNQE3PSIDAVANCNFSM4EFO3FLQ>
.
--
Martin <http://www.martiusweb.net> Richard
www.martiusweb.net
|
The point is, if we use subprocess inside executors, it work without issues. Also call the normal subprocess inside loop work with attach a streamreader to output. But the subprocess from uvloop hungs |
any news to this? the HA community is waiting for a solution wistfully ;) |
Hm very sad that its not going on here :( I would love using the HA stream component... |
I still haven't received any clear answer to #118 (comment). I know that uvloop is blocking when
Does uvloop behave differently from asyncio in your case? |
Great, I'm working on a release right now, and will likely merge #268 or a variation of it. |
Hi there, I got some details after encountering another blocking case. I found that if you provide a value for the keyword argument Here is a simple test to reproduce the behavior. It's relying on slowfs.
You should see that Python is blocking during 5 seconds. This is related to the delay enforced by slowfs. Here is the content of subprocess_test.py: import asyncio
import datetime
import subprocess
import uvloop
async def subprocess_task():
await asyncio.sleep(2)
process = await asyncio.create_subprocess_shell("touch a_file.txt" , cwd="/home_slow/",)
await process.wait()
print("Process terminated with code", process.returncode, flush=True)
async def print_task():
"""
Print seconds elapsed since beginning of the program at 1Hz.
"""
start_time = datetime.datetime.now()
while True:
now = datetime.datetime.now()
print(round((now - start_time).total_seconds()), flush=True)
await asyncio.sleep(1)
if __name__ == "__main__":
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
loop = asyncio.get_event_loop()
task_1 = loop.create_task(print_task())
task_2 = loop.create_task(subprocess_task())
try:
loop.run_forever()
except KeyboardInterrupt:
task_1.cancel()
task_2.cancel()
loop.close() Here's the config used in slowfs.cfg:
By the way, #268 doesn't solve the issue regarding using a preexec function. The way I tested it is by defining a function that does a simple Hope that could help to slove this issue. |
hi, would be |
Nice, that's great! Thanks for the slowfs tip, I didn't know about it before.
Unfortunately no, they would still block. |
@1st1 thanks for reply. `would be concurrent.futures import ProcessPoolExecutor a workaround? Unfortunately no, they would still block.` |
@1st1 here is possible fix def run_subprocess(cmd, loop=None):
loop = loop or asyncio.get_event_loop()
try:
process = await asyncio.create_subprocess_shell(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except NotImplementedError:
with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) as process:
try:
result = await loop.run_in_executor(None, process.communicate)
except Exception: # muh pycodestyle
def kill():
process.kill()
process.wait()
await loop.run_in_executor(None, kill)
raise
else:
result = await process.communicate()
return [res.decode('utf-8') for res in result] ``` |
OK, this turns out to be an issue in libuv. libuv created a pipe (marked close-on-exec) for the parent process to wait for the At the same time, CPython subprocess (used by asyncio) seems to have a similar design and the same issue. It creates an |
I don't know if it's related to this issue, but I may have another case that might help shed light on this. I haven't got it reduced to a self-contained reproducible example yet, but I could probably do that with only an hour of work if it would help. In my situation, under Python 3.8.0 (custom ARM v7 build, nothing special about it), with either uvloop 0.14.0 or 0.15.3, it appears if I cancel() a task that is launching a subprocess via I've got a stress test loop running that triggers the task that does this, cancelling it a random amount of time later, from 0.001s to a few seconds. I haven't yet narrowed down exactly when this occurs, but so far it's only when the Update/edit: it appears possible the fact I'm sometimes cancelling just as the subprocess launches is not part of the problem. I'm continuing to try reducing this to its simplest form... |
PYTHONASYNCIODEBUG
in env?: n.a.Hi there,
I'm facing the same problem encountered in CPython issue #414. Since the patch (see issue #428) is not upstreamed in asyncio yet, I was wondering if there is any progess on this in uvloop.
I've tested that behavior with the 0.9.0 version and it seems to be still blocking.
@1st1, have you planned to fix this? Do you need help at some point? (I was working with @Martiusweb on the codebase which led to those issues)
The text was updated successfully, but these errors were encountered: