-
-
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
[Bug] yarn v2 does not forward SIGTERM to child processes #991
Comments
Also, please take a look at the issue I raised on yarn v1 when considering a strategy for this: yarnpkg/yarn#4667 The strategy taken when fixing it on v1 ignored Unix standards, by always killing children immediately and ignoring the child's exit status, which caused numerous problems (which you can see from the comments on that issue) |
I just found this issue again - one thing I'd like to be sure I understand: when pressing ^C, SIGINT is sent to all the process from the group. We're actually just ignoring this signal while a child process is running, since the SIGINT will cause the child to abort, and us as well once that happens. Why isn't it the same for SIGTERM? Why do we need to forward it to the children? Shouldn't K8s send the SIGTERM to all the children from the group? Do you have documentation on this behaviour? |
This isn't related to k8s, it can be reproduced using a simple The cause appears to be some unexpected signal handling in node. Sending a signal using e.g. You can verify all of this using: // test.js
const {execFileSync} = require('child_process');
console.log('outer: pid', process.pid);
execFileSync(process.execPath, [__dirname + '/test-inner.js'], {
stdio: ['ignore', 1, 2],
}); and // test-inner.js
console.log('inner: pid', process.pid);
process.on('SIGINT', () => {
console.log('inner: sigint');
process.exit(0);
});
process.on('SIGTERM', () => {
console.log('inner: sigterm');
process.exit(0);
});
// equivalent to "while (true) {}" but async to allow event loop to continue
(function loop() {
setTimeout(loop, 0);
})(); the output is:
|
Looking at this post, I think I can make some sense of it:
That would explain why the SIGINT goes down until it reaches the children, whereas the SIGTERM With that in mind, remains to figure out what's the correct behaviour ... shouldn't tools such as K8s send the SIGTERM signal to the process group, hence following the same behaviour as what ^C does? On the other hand, it may make sense for the parent to explicitly decide whether the signals should be forwarded or not. |
@bgotink I think this is strange but not entirely unexpected behaviour. Here is where the POSIX standard describes a INTR https://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap11.html#tag_11_01_09 So the nub of it is that it is up to parent processes to forward signals in any POSIX system. With Yarn, as it is executing one process on behalf of the user (sort of as a proxy, where it sets up a certain environment for the child process), I would expect it to forward those signals (as it's not a daemon manager or some such). I would also expect (as there is a 1:1 relationship with the parent and child process) that it would wait a reasonable amount of time for the child to exit and pass any exit code from the child as its own exit code. |
Wouldn't that cause double signals to reach the underlying tool? For example, in the case of |
Can we detect if a SIGINT originates from a ctrl-c? If not, would it make sense to forward all signals except SIGINT and SIGQUIT? SIGINT and SIGQUIT are meant as signals sent by terminals (source), i.e. by humans. These user interactions send both of these signals to the entire process group instead of only the parent process (source). |
@bgotink My understanding is that INTR is unwrapped in to SIGINT outside the process so there is no way to know where it originated from (without some awful voodoo magic, which I wouldn't recommend) @arcanis I think this is a tricky one because I don't think there is a great deal in the spec about SIGINT and what really to do with it (it's left up to the application). Really, in the spirit of SIGINT, docker-compose should not be interpreting two SIGINTs as a SIGKILL (because that's what SIGKILL is for!). My vote would still be that forwarding all signals makes sense because worse than an application doing something weird with two SIGINTs is having child processes mounting up. At least in the former the damage will be limited to those applications with the esoteric signal handling behaviour, in the latter it is a universal problem that all child processes who receive a non ^c SIGINT will continue to run without their parent (which in a |
Btw, docker-compose itself forwards signals and waits 10 seconds for children to exit before sending a SIGKILL … https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop. I get that the context is a little different when you have something running in viz, but still. |
I was expecting this answer as I couldn't find anything on it. Interpreting two consecutive SIGINTs as a SIGTERM is something we see more often than just docker-compose, e.g. in the node repl. |
@bgotink Weirdly
The output:
|
Ah I assume the node repl puts the stdin in raw mode, which disables the entire INTR behaviour.
Still, given the default behaviour of the signals caused by user interaction (SIGINT with INTR, SIGQUIT with its analogous QUIT, SIGTSTP and its analogous SUSP) I would propose not forwarding those signals. |
Actually, on further reviewing the behaviour of yarn v2's @mprast I get the issue with k8s and docker in general, which is that they advocate there being just 1 process that controls all its children. For this particular issue I advocate using an init wrapper script like https://github.com/Yelp/dumb-init (which can be the If people are still really struggling I could see one possibility being a simple flag to |
yeah FWIW I ended up using a k8s preStop hook - seems like they had a workaround kind of built-in already. |
This is important |
See #1741 |
Describe the bug
This appears to be a regression from yarnpkg/yarn#3424.
Doing a
kill
on theyarn run
process will leave the other processes hanging around. To me it seems that the correct behavior should be to forward the SIGTERM to any child processes that yarn has created.Would be great to have this fixed since it is a prereq for me using
yarn run
in production, which I believe I need to do to use PnP in prod (unless there's another way!). Kubernetes uses SIGTERM to signal containers to gracefully shut down and right now yarn doesn't fit into that workflow because it can't handle the signal.To Reproduce
Couldn't figure out how to repro using Sherlock. As mentioned earlier, the reference link in the sherlock documentation is broken.
Here's a minimal repro. To see the behavior, clone the repo, then:
yarn run http-server
in one windowps ax | grep http-server
in another. You should see 3 processes, withnode /usr/bin/yarn run http-server
as the top process.kill
the PID of the top process.ps ax | grep http-server
again. You'll see that the top process is gone, but the other two remain.Environment if relevant (please complete the following information):
Thank you!
The text was updated successfully, but these errors were encountered: