webpack-dev-server icon indicating copy to clipboard operation
webpack-dev-server copied to clipboard

`webpack-dev-server` cannot be killed when spawned with `child_process`

Open AaronBeaudoin opened this issue 6 years ago • 20 comments

  • 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.

AaronBeaudoin avatar Aug 01 '19 16:08 AaronBeaudoin

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

alexander-akait avatar Aug 01 '19 16:08 alexander-akait

Here explain https://github.com/webpack/webpack-dev-server/issues/1479#issuecomment-442492922

alexander-akait avatar Aug 01 '19 16:08 alexander-akait

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 avatar Aug 01 '19 17:08 AaronBeaudoin

@AaronBeaudoin try to use 10 seconds or more

alexander-akait avatar Aug 01 '19 17:08 alexander-akait

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.

AaronBeaudoin avatar Aug 01 '19 18:08 AaronBeaudoin

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 avatar Aug 01 '19 18:08 AaronBeaudoin

@AaronBeaudoin thanks for investigation, we look on this in near future, anyway feel free to debug and send a PR with fix

alexander-akait avatar Aug 02 '19 11:08 alexander-akait

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 avatar Aug 02 '19 15:08 AaronBeaudoin

@AaronBeaudoin maybe it is only on windows, can you sty this on linux?

alexander-akait avatar Aug 02 '19 15:08 alexander-akait

Is there a solution?

xiaoyouyu avatar Oct 21 '19 03:10 xiaoyouyu

var exec = require('child_process').execSync; exec(’webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --useLocalIp‘, { stdio: 'inherit' })

image

@evilebottnawi Please, How to kill this process?

xiaoyouyu avatar Oct 21 '19 04:10 xiaoyouyu

@xiaoyouyu better use execa and use something like this:

setTimeout(() => {
	subprocess.kill('SIGTERM', {
		forceKillAfterTimeout: 2000
	});
}, 1000);

alexander-akait avatar Oct 21 '19 11:10 alexander-akait

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);
    }
};

ifedyukin avatar Nov 18 '19 15:11 ifedyukin

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);
    }
};

How to get the childProcess

xiaoyouyu avatar Nov 19 '19 07:11 xiaoyouyu

@xiaoyouyu better use execa and 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 avatar Nov 19 '19 08:11 xiaoyouyu

@xiaoyouyu I started WDS using spawn and it returns ChildProcess object that contains pid field.

ifedyukin avatar Nov 20 '19 13:11 ifedyukin

/cc @hiroppy we have same problems with webpack-cli, investigate

alexander-akait avatar Apr 15 '20 10:04 alexander-akait

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. 🤔

tkctly avatar Nov 16 '20 11:11 tkctly

@Jfreey please tell the version of wepack, webpack-cli & webpack-dev-server.

snitin315 avatar Nov 16 '20 11:11 snitin315

@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...

tkctly avatar Nov 17 '20 01:11 tkctly

I think we can close it - no activity, if you faced with this problem again feel free to open a new issue

alexander-akait avatar Sep 27 '22 01:09 alexander-akait

@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

nsunga avatar Jul 20 '23 22:07 nsunga

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 avatar Dec 19 '23 15:12 matthiasgeihs

@matthiasgeihs Can you open a new issue with the reproducible example, thank you

alexander-akait avatar Dec 20 '23 18:12 alexander-akait

@alexander-akait created https://github.com/webpack/webpack-dev-server/issues/5026

matthiasgeihs avatar Dec 27 '23 22:12 matthiasgeihs