uv icon indicating copy to clipboard operation
uv copied to clipboard

Consider `execv` for `uv run` on Unix

Open zanieb opened this issue 1 year ago • 13 comments
trafficstars

See https://github.com/astral-sh/uv/pull/3074#issuecomment-2060847595

zanieb avatar Apr 17 '24 16:04 zanieb

Edit: The below concern has found other solutions since then, and is not really relevant.

For the https://github.com/bluss/pyproject-local-kernel usecase (sorry if this is boring), spawn vs exec would make a difference on Linux in terms of how a jupyter notebook is kernel is launched.

jupyter lab launches my python script -> launches uv run -> launches ipykernel.

My script already handles forwarding posix signals to the child (first arrow). If you use exec, the second arrow disappears and posix signals are forwarded to the ipykernel which is useful, in fact the ipykernel doesn't want to start correctly if it doesn't have that signal path. I think exec is generally what you'd want to do. I didn't run into this with rye run, because it uses exec on Linux.

I could configure my kernel with interrupt_mode=message (instead of default signal) to make this issue disappear, but maybe that shouldn't be needed. (Edit, no interrupt_mode=message is only fully supported on Linux, not on Windows, so this is not a great option).

bluss avatar Apr 21 '24 14:04 bluss

Is this still possible, how does the ephemeral venv cleanup work? Is it using a scope based cleanup. I'll file another issue that's related to ipykernel, and maybe we'll find a good solution.

bluss avatar Jul 21 '24 13:07 bluss

It is not clear how we'd clean up the ephemeral environment, that's a good question.

zanieb avatar Jul 21 '24 14:07 zanieb

It runs on Drop.

charliermarsh avatar Jul 21 '24 15:07 charliermarsh

The pyproject-local-kernel usecase seems to work perfectly on Linux now after the #5257 fix I think :star_struck:. Probably should carry over to windows too. Thanks for the help with this :slightly_smiling_face:

uv run --with ipykernel is perfect for the notebook use case, it's very smooth.

bluss avatar Jul 24 '24 18:07 bluss

Awesome. I did test on my Windows machine and it worked as expected for me, so hopefully good there too...

charliermarsh avatar Jul 24 '24 18:07 charliermarsh

When you execv is nothing dropped until the process exits? I'm quite naive as to how that is handled. cc @BurntSushi

zanieb avatar Oct 04 '24 21:10 zanieb

Basically, you can think of execv (and related functions) as like a std::process::exit. It can be inserted anywhere in your program, and it will unceremoniously stop executing the current program. Destructors are not guaranteed to run.

So to make this work here, we'd probably want to bubble some instruction to "run this exec command" to main in a way that everything else goes out of scope and gets dropped. Otherwise, you'll not just have things like an ephemeral environment hanging around, but all the various allocations and file descriptors won't get dropped either (they will eventually by the OS once the replacing process terminates, AIUI).

Also, we are very likely already using exec. I think what is meant here is that we do not want to fork before an exec. Or stated at a higher level, we want to replace the current process with the thing we want to run.

BurntSushi avatar Oct 07 '24 12:10 BurntSushi

Hm.. thanks for the details.

I think that supports my concern that we have resources e.g., the ephemeral environment, that can't be removed until the spawned process finishes which makes it hard to entirely cede control?

zanieb avatar Oct 07 '24 12:10 zanieb

Oh I see, yes, hmmm. That is a conundrum. I am reminded of a trick where you can unlink a file but keep an open file descriptor to it, which at least on Unix, will keep the file around until the descriptor is closed. But, 1) I'm not sure how to make that scale to an entire directory tree and 2) I'm not sure if that concept works on Windows. Failing some trick like that, I'd guess the only way to do this is to introduce some kind of garbage collection? Not sure.

BurntSushi avatar Oct 07 '24 13:10 BurntSushi

Yeah I think the general form of the problem here is that execv won't run Drop, but it we Drop things before deferring to execv, we'll remove things we need like temporary directories.

charliermarsh avatar Oct 08 '24 21:10 charliermarsh

This feels like a pretty significant blocker for switching to execv – I think we might need to prioritize passing signals to the child in a robust manner?

zanieb avatar Oct 08 '24 21:10 zanieb

Yeah, agreed.

charliermarsh avatar Oct 08 '24 21:10 charliermarsh