Skip to content

Dev server child process cannot be killed #5026

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

Closed
matthiasgeihs opened this issue Dec 27, 2023 · 2 comments
Closed

Dev server child process cannot be killed #5026

matthiasgeihs opened this issue Dec 27, 2023 · 2 comments

Comments

@matthiasgeihs
Copy link

matthiasgeihs commented Dec 27, 2023

Bug report

When spawning the webpack dev server via child_process.spawn in a node.js script, the child process cannot be killed via proc.kill(). If the parent process is exited via process.exit(0), the dev server child process continues running in the background and doesn't free up the bound port.

Platform: macOS 14.2.1

Relates to #2168 (comment).

Actual Behavior

proc.kill does not stop dev server.

Expected Behavior

proc.kill stops dev server.

How Do We Reproduce?

Create an npm project with the files below.
Run npm i and then npm run test.
Observe via task manager that the webpack server continues to be running in the background.

package.json

{
  "name": "webpack-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "node test.js",
    "serve": "webpack serve --mode development"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "html-webpack-plugin": "^5.6.0",
    "webpack": "^5.89.0",
    "webpack-cli": "^5.1.4",
    "webpack-dev-server": "^4.15.1"
  }
}

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'main.js',
  },
  plugins: [new HtmlWebpackPlugin()],
};

test.js

const { spawn } = require("child_process");

const proc = spawn("npm", ["run", "serve"], { stdio: "inherit" });

setTimeout(() => {
  proc.kill();
  process.exit(0);
}, 5000);

src/index.js

function component() {
  const element = document.createElement('div');
  element.innerHTML = 'Hello webpack';
  return element;
}

document.body.appendChild(component());

Output of npx webpack-cli info

% npx webpack-cli info

  System:
    OS: macOS 14.2.1
    CPU: (10) arm64 Apple M1 Pro
    Memory: 6.55 GB / 32.00 GB
  Binaries:
    Node: 21.5.0 - /opt/homebrew/bin/node
    Yarn: 3.7.0 - /opt/homebrew/bin/yarn
    npm: 10.2.4 - /opt/homebrew/bin/npm
  Browsers:
    Chrome: 120.0.6099.129
    Edge: 120.0.2210.61
    Safari: 17.2.1
  Packages:
    html-webpack-plugin: ^5.6.0 => 5.6.0 
    webpack: ^5.89.0 => 5.89.0 
    webpack-cli: ^5.1.4 => 5.1.4 
    webpack-dev-server: ^4.15.1 => 4.15.1 
@alexander-akait
Copy link
Member

The problem is in npm, just change

const { spawn } = require("child_process");

const proc = spawn("webpack", ["serve", "--mode", "development"], { stdio: "inherit" });

setTimeout(() => {
    proc.kill();
}, 5000);

This is because npm run use shell: true and shell scripts cannot be killed https://docs.npmjs.com/cli/v10/commands/npm-run-script#script-shell

@matthiasgeihs
Copy link
Author

matthiasgeihs commented May 20, 2024

Sorry for the quietness on my part.

I was trying to find some time to understand the details behind this and whether there is maybe some npm options to make this work regardless, as it would be convenient to be able to run the npm commands directly.

That being said, I just tried to reproduce the behavior and it seems like this is not an issue anymore. Node now seems to shut down the npm process and the child webpack process successfully on proc.kill.

If this is not the case on your system, you can use the following fix:

const find = require("find-process");

// Fix for webpack dev server not being killed by appProcess.kill().
const webpack = await find('port', appPort);
if (webpack.length > 0) {
  console.log(`killing ${webpack[0].name}`);
  process.kill(webpack[0].pid);
} else {
  console.log(`no process listening on ${appPort}`);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants