-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Exits with code 1 on SIGTERM without waiting for child #4667
Comments
I am very willing to commit time/code to getting this fixed properly as I think it's in a bit of a state at the moment but would like to get some agreement on direction first :) |
Has there been any more discussion on this? I agree that it might be worth taking a look at signal handling as whole; it doesn't look like SIGINT is handled at all, apart from where onDeath() handles it in mutex mode. I think it might have to be handled slightly differently, since SIGINT is sent to all the processes in the foreground group instead of needing to be forwarded through the parent. I'd also be willing to devote some time to this to draft an RFC or something like that. |
Any maintainer input on this? It seems like it prevents Yarn from being used for real in any situations where you need |
I am still getting this issue by running a process using yarn vs running it with npm run: {
"scripts": {
"test": "concurrently -k --success first \"npm run dev:test\" \"yarn jest\""
} app.js process.on('SIGTERM', async () => {
await server.close()
console.log('EXITING GRACEFULLY...')
process.exit(0)
}) WHEN USING YARN: yarn test
....
[1] Test Suites: 3 passed, 3 total
[1] Tests: 42 passed, 42 total
[1] Snapshots: 0 total
[1] Time: 15.137s
[1] Ran all test suites.
[1] yarn jest exited with code 0
--> Sending SIGTERM to other processes..
[0] EXITING GRACEFULLY...
[0] yarn dev:test exited with code 1
✨ Done in 16.58s. WHEN USING NPM RUN: yarn test
...
[1] Test Suites: 3 passed, 3 total
[1] Tests: 42 passed, 42 total
[1] Snapshots: 0 total
[1] Time: 15.138s
[1] Ran all test suites.
[1] yarn jest exited with code 0
--> Sending SIGTERM to other processes..
[0] EXITING GRACEFULLY...
[0] npm run dev:test exited with code 0
✨ Done in 16.54s. So with npm run running my server I can remove the System Info: >>> yarn -v
1.6.0
>>> npm -v
5.6.0
>>> node -v
v10.0.0 Also I am not using |
Same problem. $ yarn -v
1.12.3
$ node -v
v8.12.0
$ npm -v
6.4.1
$ node index.js
^C
Doing async cleaning
Done
$ npm start
^C
Doing async cleaning
Doing async cleaning
Done
$ yarn start
yarn run v1.12.3
^C
Doing async cleaning
$ Done # <--- Console.log('Done') ends up on new line in console, because yarn already quit. To test: {
"scripts": {
"start": "node index.js"
}
} --index.js-- process.stdin.resume();
process.on('SIGINT', () => {
console.log('\n');
console.log('Doing async cleaning');
setTimeout(() => {
console.log('Done');
process.exit(0);
}, 500);
}); |
Agreed, this makes it impossible to use |
Here is what I ended up doing: // The following captures keypress events and effectively blocks any of the
// CTRL+C/CTRL+Z/CTRL+D combinations from sending their respective signals.
readline.emitKeypressEvents(process.stdin)
if (process.stdin.isTTY) process.stdin.setRawMode(true)
process.stdin.on('keypress', (char, key) => {
if (key.ctrl && key.name === 'c') {
console.log("Caught CTRL+C and asking you to wait for this process to exit gracefully, mi'lord.")
const exitCode = 0
cleanupHandler(exitCode)
}
}) |
Same here, any ideas if this can be fixed? |
Issue is still valid, is there any progress? This can be reproduced with a very simple setup script const wait = waitTime => new Promise(resolve => setTimeout(resolve, waitTime));
setInterval(() => {
console.log("interval");
}, 1000);
process.on('SIGINT', async () => {
console.log('caught');
await wait(1000);
console.log('killing');
process.exit(0);
}); when doing |
I'm seeing this issue in yarn v1.22.4 but not in npm v6.12.0 It makes yarn unusable 😢 |
@aleclarson my feeling is that attention now needs to moved to yarn v2 to get this fixed. They actually have a regression on issue #3424 (the fix for which created this bug). I have commented on the issue on v2 that talks about this regression asking whoever implements a solution for it to consider this documented behaviour in order to avoid these problems. (see yarnpkg/berry#991) |
After some careful review (read yarnpkg/berry#991 for all the juicy details) the new behaviour I mentioned in v2 is actually desirable and the nub of it is that this is no longer a problem in v2 (yarn's exit status is the exit status of the child process). I will leave this open in case someone wants to either backport how it works in v2 to here (which might cause more problems if people rely on v1's behaviour) or fix the issue for v1, but for anyone who wants a solution to this now I recommend upgrading to v2! |
When sending a SIGTERM, yarn doesn't wait for its children before exiting[1]. This commit removes the use of `yarn` in bs-wrapper. This should be fine, because yarn was only used for setting the environment (mostly PATH). Since bs-wrapper is run via yarn scripts, the environment should already be set up. This commit also changes bs-wrapper to make sure to send SIGTERM only once if child process sends more data to STDOUT before exiting. [1]: yarnpkg/yarn#4667
When sending a SIGTERM, yarn doesn't wait for its children before exiting[1]. This commit removes the use of `yarn` in bs-wrapper. This should be fine, because yarn was only used for setting the environment (mostly PATH). Since bs-wrapper is run via yarn scripts, the environment should already be set up. This commit also changes bs-wrapper to make sure to send SIGTERM only once if child process sends more data to STDOUT before exiting. [1]: yarnpkg/yarn#4667
When sending a SIGTERM, yarn doesn't wait for its children before exiting[1]. This commit removes the use of `yarn` in bs-wrapper. This should be fine, because yarn was only used for setting the environment (mostly PATH). Since bs-wrapper is run via yarn scripts, the environment should already be set up. This commit also changes bs-wrapper to make sure to send SIGTERM only once if child process sends more data to STDOUT before exiting. [1]: yarnpkg/yarn#4667
Whatever is happening with this issue, it's still an annoyance. I ended up throwing together a tiny wrapper script -- my use case is that I use yarn and |
Sample code for a run script with multiple arguments: yarn run commands "command1" "command2" "etc"
|
**Public-Facing Changes** Improved ^C exit behavior for `npx @foxglove/ws-protocol-examples`. Updated TypeScript examples to use schemas from `@foxglove/schemas`. **Description** Our server scripts weren't shutting down cleanly on sigint. I thought `ws.close()` would work, but for some unknown reason I had to manually `close()` each of the currently open clients as well. Additionally, Yarn 1 doesn't wait for the child process before it exits (yarnpkg/yarn#4667) which is probably why I didn't notice the issue when originally creating these scripts. Fixes #162
Is this issue still unresolved? |
This is a major issue for shutdown handling when using yarn berry or yarn v1. Node will not update the version of yarn in the docker image and yarn seemingly will not backport the fix to yarn v1, so you have to manually update the global yarn in your own docker images before using it to run apps with yarn inside docker. |
) **Public-Facing Changes** Improved ^C exit behavior for `npx @foxglove/ws-protocol-examples`. Updated TypeScript examples to use schemas from `@foxglove/schemas`. **Description** Our server scripts weren't shutting down cleanly on sigint. I thought `ws.close()` would work, but for some unknown reason I had to manually `close()` each of the currently open clients as well. Additionally, Yarn 1 doesn't wait for the child process before it exits (yarnpkg/yarn#4667) which is probably why I didn't notice the issue when originally creating these scripts. Fixes foxglove#162
Do you want to request a feature or report a bug?
This is a bug
What is the current behavior?
Currently yarn terminates with exit code 1 when it receives a SIGTERM without waiting for the child to exit and without passing its child's exit status up the chain.
The issue that this stemmed from was about handling SIGTERM events (#3424) and was introduced in pull request #3789.
If the current behavior is a bug, please provide the steps to reproduce.
Create a simple express script:
Note that the script uses
setTimeout
to wait before exiting (as if it is waiting 1s for a client connection to end).In another session run the following with the PID of that command:
Finally in that first session after it has exited:
You can see that it exits immediately (not waiting 1s) and the error code is 1.
What is the expected behavior?
Expected behaviour is to do exactly as node would:
This waits the 1s for the
setTimeout
(we kill usingkill $PID
in between the node and echo commands as above). You can also see we get the child's exit status (you can verify this by setting it to something else likeprocess.exit(9)
and seeing it come out).I see some comments in the code where it is questioning what we should do about this:
yarn/src/util/signal-handler.js
Lines 6 to 8 in daa599d
I think it's the child's job to decide what to do if a SIGTERM event is received. The parent should hand the signal to the child and wait to see if it exits. The only thing that I think Yarn should consider is whether there is a time limit that we would like to wait for naughty child processes that do not exit on time. Docker sets this to 10 seconds, whatever we set this to (if we do at all!!) we should make it a) clear and b) configurable.
One other thing: currently not sure what we do with SIGINT. I see weird stuff happening with that too (and I presume other signals?). Probably worth investigating signal handling more holistically?
Please mention your node.js, yarn and operating system version.
The text was updated successfully, but these errors were encountered: