`webpack-dev-server` cannot be killed when spawned with `child_process`
- Operating System: Windows 10.0.17134 Build 17134
- Node Version: 8.11.1
- NPM Version: 5.6.0
- webpack Version: 4.39.0
- webpack-dev-server Version: 3.7.2
- Browser: Not Applicable
- [x] This is a bug
- [ ] This is a modification request
Expected Behavior
webpack-dev-server should be killed with childProcess.kill() after spawning it with require("child_process").spawn().
Actual Behavior
webpack-dev-server is orphaned instead of being killed in the above scenario.
Steps to Reproduce
Create a folder with the following package.json:
{
"name": "webpack-dev-server-process-exit-bug-test",
"dependencies": {
"webpack": "^4.39.0",
"webpack-cli": "^3.3.6",
"webpack-dev-server": "^3.7.2"
}
}
Add a test.js file:
const { spawn: spawnProcess } = require("child_process");
let devServerProcess = spawnProcess(
".\\node_modules\\.bin\\webpack-dev-server", [],
{ shell: true, stdio: "inherit" });
setTimeout(_ => {
devServerProcess.kill();
console.log("Trying to kill webpack-dev-server...");
}, 5000);
Add a src.js file to satisfy the webpack zero-config defaults:
console.log("test");
Run npm i then node test.js and check the running processes on your system. The webpack-dev-server node has not been killed as expected.
Note
This issue still occurs when the stdio option is not supplied to the spawn function.
I think duplicate https://github.com/webpack/webpack-dev-server/issues/1479, we can't kill process when webpack do compilation right now, also it is unsafe for cache
Here explain https://github.com/webpack/webpack-dev-server/issues/1479#issuecomment-442492922
If I comment out the setTimeout call in my code above and instead just use [ctrl]+[c] manually after about 5 seconds then all processes seem to be killed properly. According to the issue you referenced, shouldn't this problem still be occurring is such a scenario?
@AaronBeaudoin try to use 10 seconds or more
If the point is to ensure that compiling has completed before trying to kill the process then it's irrelevant. I get the Compiled successfully. message after about a second or two. Therefore the process is definitely not getting killed in the middle of compilation.
Also it seems that using the fork function instead of the spawn function solves the issue as well:
const { fork: forkProcess } = require("child_process");
let devServerProcess = forkProcess(
".\\node_modules\\webpack-dev-server\\bin\\webpack-dev-server.js", []);
setTimeout(_ => {
devServerProcess.kill();
console.log("Trying to kill webpack-dev-server...");
}, 5000);
@AaronBeaudoin thanks for investigation, we look on this in near future, anyway feel free to debug and send a PR with fix
In case it helps, it seems that when spawning processes with spawn and the shell option is set to true, an invisible cmd.exe window is created with the process running inside of it. I found that when calling childProcess.kill() the cmd.exe window is properly killed; it's just the webpack-dev-server process that was inside of it which is left still running.
@AaronBeaudoin maybe it is only on windows, can you sty this on linux?
Is there a solution?
var exec = require('child_process').execSync; exec(’webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --useLocalIp‘, { stdio: 'inherit' })

@evilebottnawi Please, How to kill this process?
@xiaoyouyu better use execa and use something like this:
setTimeout(() => {
subprocess.kill('SIGTERM', {
forceKillAfterTimeout: 2000
});
}, 1000);
In my case I've solved same issue by next steps:
Firstly added Windows-specific code to emit SIGINT process event.
const rl = require('readline');
if (/^win/.test(process.platform)) {
rl.createInterface({
input: process.stdin,
output: process.stdout
}).on('SIGINT', () => process.emit('SIGINT'));
}
Secondly added specific code to kill process on different OS.
const { execSync } = require('child_process');
function killChildProcess(childProcess) {
if (/^win/.test(process.platform)) {
execSync(`taskkill /pid ${childProcess.pid} /f /t`);
} else {
process.kill(childProcess.pid);
}
};
In my case I've solved same issue by next steps:
Firstly added Windows-specific code to emit
SIGINTprocess event.const rl = require('readline'); if (/^win/.test(process.platform)) { rl.createInterface({ input: process.stdin, output: process.stdout }).on('SIGINT', () => process.emit('SIGINT')); }Secondly added specific code to kill process on different OS.
const { execSync } = require('child_process'); function killChildProcess(childProcess) { if (/^win/.test(process.platform)) { execSync(`taskkill /pid ${childProcess.pid} /f /t`); } else { process.kill(childProcess.pid); } };
How to get the childProcess
@xiaoyouyu better use
execaand use something like this:setTimeout(() => { subprocess.kill('SIGTERM', { forceKillAfterTimeout: 2000 }); }, 1000);
@ifedyukin 干的漂亮
const execa = require('execa'); await execa('webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --useLocalIp', { stdio: 'inherit' });
@xiaoyouyu I started WDS using spawn and it returns ChildProcess object that contains pid field.
/cc @hiroppy we have same problems with webpack-cli, investigate
I found a description for an option with this document #devserverstdin---cli-only.
But when I use --stdin, it throw an Error: ValidationError: webpack Dev Server Invalid Options
The code about this option was already used at there https://github.com/webpack/webpack-dev-server/blob/c9e9178a4882e414a6b9616baa35e8dbf7b2dd75/lib/utils/createConfig.js#L83-L90
But in options.json I can't found the schema with stdin.
I add the stdin schema in the options.json.
ummmm,Seems to work……
But why?The documents tall me, you can use it. But the fact is that it cannot be used.
This confused me. 🤔
@Jfreey please tell the version of wepack, webpack-cli & webpack-dev-server.
@Jfreey please tell the version of
wepack,webpack-cli&webpack-dev-server.
@snitin315 Please check
This is the package.json from the demo project:
{
"name": "dev_server_stdin_bug",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"devDependencies": {
"webpack": "^5.4.0",
"webpack-cli": "^4.2.0",
"webpack-dev-server": "^3.11.0"
}
}
I add the property to options.json in my local source code :
"stdin":{
"type": "boolean"
},
The code is below this line: https://github.com/webpack/webpack-dev-server/blob/4ab1f21bc85cc1695255c739160ad00dc14375f1/lib/options.json#L362-L381
Well then, It can work...
I think we can close it - no activity, if you faced with this problem again feel free to open a new issue
@AaronBeaudoin were u able to solve this?
When running wds through child_process.spawn(), im able to reproduce:
this message just hangs [webpack-dev-server] Gracefully shutting down. To force exit, press ^C again. Please wait...
But when I run wds through command line ie. node node_modules/webpack-dev-server/bin/webpack-dev-server.js ..., I still get the message but importantly, the process gets killed
Having the same issue (on MacOS).
const appProcess = spawn("npm", ["run", "serve"]); // runs "webpack serve"
...
appProcess.kill(); // returns true, but "webpack" still running
@alexander-akait
@matthiasgeihs Can you open a new issue with the reproducible example, thank you
@alexander-akait created https://github.com/webpack/webpack-dev-server/issues/5026