-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
uv run without --script forks thousands of processes, then fails, on file without .py extension #11220
Comments
Thanks! I believe this is a duplicate of #6360. |
@charliermarsh yeah, this is the same failure mode. I guess the additional question or feature request here is "is there a way to make uv handle this class of pebkac more gracefully?" As noted above, I think it's reasonable for |
I think the two ways I could imagine trying to "solve" this would be:
Both of these feel a bit kludgy to me, but I think both could probably be made to work well enough to catch most reasonable ways that a user might make these mistakes. I'd be happy to take a look at implementing one or the other of these as options if there's interest. |
Yeah I think it makes sense to try and do a bit better here... There have been a few other requests too that would benefit from somehow having access to the command we're running. |
@charliermarsh would you be interested in seeing a PR toward either of the potential fixes outlined above? Without having dug too much into the details, I think one concrete proposal toward (1) might be something like: Whenever I think this would be a fairly robust and low-overhead way to catch the recursion issue here without needing to know more semantic information about the file being executed. But there are certainly other reasonable options. |
I'm fine with that. Random thoughts...
|
Possibly... You already have access to |
For |
|
I think a default |
Handle potential infinite recursion if `uv run` recursively invokes `uv run`. This can happen if the shebang line of a script includes `uv run`. Handled by adding a new environment variable `UV_RUN_RECURSION_DEPTH`, which contains a counter of the number of times that uv run has been transitively invoked. If unset, it defaults to zero, and each time uv run starts a subprocess it increments the counter. Closes astral-sh#11220.
Handle potential infinite recursion if `uv run` recursively invokes `uv run`. This can happen if the shebang line of a script includes `uv run`. Handled by adding a new environment variable `UV_RUN_RECURSION_DEPTH`, which contains a counter of the number of times that uv run has been transitively invoked. If unset, it defaults to zero, and each time uv run starts a subprocess it increments the counter. Closes astral-sh#11220.
Handle potential infinite recursion if `uv run` recursively invokes `uv run`. This can happen if the shebang line of a script includes `uv run`. Handled by adding a new environment variable `UV_RUN_RECURSION_DEPTH`, which contains a counter of the number of times that uv run has been transitively invoked. If unset, it defaults to zero, and each time uv run starts a subprocess it increments the counter. Closes astral-sh#11220.
Handle potential infinite recursion if `uv run` recursively invokes `uv run`. This can happen if the shebang line of a script includes `uv run`. Handled by adding a new environment variable `UV_RUN_RECURSION_DEPTH`, which contains a counter of the number of times that uv run has been transitively invoked. If unset, it defaults to zero, and each time uv run starts a subprocess it increments the counter. Closes astral-sh#11220.
Handle potential infinite recursion if `uv run` recursively invokes `uv run`. This can happen if the shebang line of a script includes `uv run`. Handled by adding a new environment variable `UV_RUN_RECURSION_DEPTH`, which contains a counter of the number of times that uv run has been transitively invoked. If unset, it defaults to zero, and each time uv run starts a subprocess it increments the counter. Closes astral-sh#11220.
Handle potential infinite recursion if `uv run` recursively invokes `uv run`. This can happen if the shebang line of a script includes `uv run`. Handled by adding a new environment variable `UV_RUN_RECURSION_DEPTH`, which contains a counter of the number of times that uv run has been transitively invoked. If unset, it defaults to zero, and each time uv run starts a subprocess it increments the counter. Closes astral-sh#11220.
@zanieb @charliermarsh: PR with an initial crack at the infinite recursion detection here: #11386 |
Handle potential infinite recursion if `uv run` recursively invokes `uv run`. This can happen if the shebang line of a script includes `uv run`. Handled by adding a new environment variable `UV_RUN_RECURSION_DEPTH`, which contains a counter of the number of times that uv run has been transitively invoked. If unset, it defaults to zero, and each time uv run starts a subprocess it increments the counter. Closes astral-sh#11220.
Handle potential infinite recursion if `uv run` recursively invokes `uv run`. This can happen if the shebang line of a script includes `uv run`. Handled by adding a new environment variable `UV_RUN_RECURSION_DEPTH`, which contains a counter of the number of times that uv run has been transitively invoked. If unset, it defaults to zero, and each time uv run starts a subprocess it increments the counter. Closes astral-sh#11220.
Handle potential infinite recursion if `uv run` recursively invokes `uv run`. This can happen if the shebang line of a script includes `uv run` without passing --script. Handled by adding a new environment variable, `UV_RUN_RECURSION_DEPTH`, which contains a counter of the number of times that uv run has been recursively invoked. If unset, it defaults to zero, and each time uv run starts a subprocess it increments the counter. Closes astral-sh#11220.
Handle potential infinite recursion if `uv run` recursively invokes `uv run`. This can happen if the shebang line of a script includes `uv run` without passing --script. Handled by adding a new environment variable, `UV_RUN_RECURSION_DEPTH`, which contains a counter of the number of times that uv run has been recursively invoked. If unset, it defaults to zero, and each time uv run starts a subprocess it increments the counter. Closes astral-sh#11220.
Handle potential infinite recursion if `uv run` recursively invokes `uv run`. This can happen if the shebang line of a script includes `uv run` without passing --script. Handled by adding a new environment variable, `UV_RUN_RECURSION_DEPTH`, which contains a counter of the number of times that uv run has been recursively invoked. If unset, it defaults to zero, and each time uv run starts a subprocess it increments the counter. Closes astral-sh#11220.
Summary
One of the most useful features of
uv
, for me, is the ability to define small utility scripts packaged alongside their dependencies. This allows me to easily use Python for many of the things I would have previously used bash for. This becomes particularly nice when using uv as your shebang line.I recently did this on a small helper script which did not have a
.py
extension and I forgot to include--script
. The following reproduces the scenario:Running this input causes uv to hang for a while, consuming a large amount of memory (around 8GB), before eventually failing:
Looking at the processes on my machine during the hang, it appears that uv is spawning hundreds to thousands of subprocesses:
I assume there's some kind of recursion happening here which is effectively causing uv to forkbomb my machine.
The issue described here goes away if I add
--script
to the shebang line of my script, or if I rename the file torepro.py
.I don't necessarily expect uv to support the way I've invoked it here. It seems reasonable to me that
uv run
requires the--script
flag when running a file without a.py
extension, but it would be nice if it handled this class of user error a bit more gracefully.Platform
Ubuntu 24.04, Linux 6.8.0-52-generic x86_64 GNU/Linux
Version
uv 0.5.27
Python version
Python 3.12.3
The text was updated successfully, but these errors were encountered: