-
Notifications
You must be signed in to change notification settings - Fork 543
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
(Linux) The stage-1 bootstrap script does not propagate certain signals to the stage-2 bootstrap script. #2043
Comments
Oh yeah, I vaguely recall this being fixed in the original bootstrap. Yeah, I see a bunch of code for this in the original. Yeah, this is platform specific in some way. In my own system (some ubuntu/debian thing), I don't see this behavior (ctrl+c is received by python)
This SGTM. It just needs to special case the zip case to not use exec -- Is there a way to tell the shell to forward on signals to the child process? That would make this a lot easier. |
Posterity: My repro was just a simple shell script and python program:
Does the above program also exhibit the issue of signals not being received by the child process? Searching around a bit, I couldn't find a mention of this divergent behavior for centos + debian. |
Ah yeah - I didn't notice that was being handled in stage 1.
(EDIT: sorry, don't know why I started talking about Windows)
It'll propagate a CTRL+C, but try sending a |
Thanks for the PR. I'll have a look in the next day or so. I think I understand what's going on now. This is some shell arcana that seems WAI. From what I can find, CTRL+C (the keyboard event) is slightly different than If you have e.g. a shell script that runs a stage1-based program, then, when it asks what the child process pid is, it'll get the pid of the stage1 bash process ("pid1"). That there is a subprocess for the python program ("pid2") is hidden from it. So, a workaround is to use I looked around to see if bash can be made to forward a signal along. It sort of can, but sigint in particular looks tricky. The basic trick is to use trap, and background process, and wait:
This will work for e.g. sigterm, but not sigint. Why? Because when bash starts a background job ( Ignoring this case for zips I think is fine for now. It would be nice if zips didn't have this problem, too, though. I don't like having to jump through hoops on the shell side, though. This is a relatively obscure behavior. If we could get move into the stage2 logic, then this would probably work better overall. The [1] I'm not sure if this is bash specific or most shells |
When the two-stage bootstrap is used, the parent shell process runs python as a child process, which changes how signals are propagated. Specifically, if a signal is sent _directly_ to the parent (e.g. `kill $parent`), the child process (python) won't receive it and it will appear to be ignored. This is because the parent process is busy waiting for the child process. To fix, invoke the python process using `exec` instead. Because the process is entirely replaced, signals are sent directly to the replacement. This can't be used for zip files, though, because they rely on a catching the exit signal to perform cleanup of the extracted files. Fixes #2043 --------- Co-authored-by: Richard Levasseur <[email protected]>
Posterity: Zip builds will still ignore signals. I don't think I'll come back around to addressing that any time soon (if ever). That said, after #2052, it should be possible to have the second stage bootstrap handle deleting the temporary directory the zip files are extracted into, which allows stage1 to call exec on the extracted files in temp. It just requires doing something like this in the second stage code:
|
🐞 bug report
Affected Rule
The issue is caused by the rule:
py_binary
/py_test
Is this a regression?
Yes.
Description
(This bug report is specific to Linux)
In the old 1-stage bootstrap script, the script eventually runs the underlying program with
os.execv
, which replaces the process entirely, so that's ok - any signals get propagated directly to our program.https://github.com/bazelbuild/rules_python/blob/main/python/private/python_bootstrap_template.txt#L379-L386
In the new 2-stage boostrap script(s), the first stage invokes the second stage directly:
https://github.com/bazelbuild/rules_python/blob/main/python/private/stage1_bootstrap_template.sh#L111-L116
I'm not sure if it's platform depedent - but at least on Debian and CentOS, bash will start a child process, and signals like SIGINT don't get handled nor propagated.
I think this is a simple fix, changing the stage-2 invocation to:
I'm happy to raise a PR for the above if it is agreed to be OK.
🔬 Minimal Reproduction
I don't have one at hand, but I can provide one if needed.
🌍 Your Environment
Operating System:
Linux AMD64 - CentOS 7, and Debian 11
Output of
bazel version
:Bazel 7.2.1
Rules_python version:
0.34.0
The text was updated successfully, but these errors were encountered: