From f81a5e87ed527a705ae2fc5b71332dd17e5a6a94 Mon Sep 17 00:00:00 2001 From: Anders Kaseorg Date: Tue, 6 Oct 2020 17:15:26 -0700 Subject: [PATCH] run-dev: Wait for children to exit on Ctrl+C after killing them. In addition to being generally more correct, this works around a bug in Node.js that causes webpack-dev-server to corrupt the terminal state when exiting as a background process. https://github.com/nodejs/node/issues/35536 Signed-off-by: Anders Kaseorg --- tools/run-dev.py | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/tools/run-dev.py b/tools/run-dev.py index a0178f802e..145b8774a3 100755 --- a/tools/run-dev.py +++ b/tools/run-dev.py @@ -5,7 +5,6 @@ import pwd import signal import subprocess import sys -import traceback from typing import Any, Callable, Generator, List, Sequence from urllib.parse import urlunparse @@ -164,7 +163,7 @@ def do_one_time_webpack_compile() -> None: # with a running development server. subprocess.check_call(['./tools/webpack', '--quiet', '--test']) -def start_webpack_watcher() -> None: +def start_webpack_watcher() -> "subprocess.Popen[bytes]": webpack_cmd = ['./tools/webpack', '--watch', f'--port={webpack_port}'] if options.minify: webpack_cmd.append('--minify') @@ -176,7 +175,7 @@ def start_webpack_watcher() -> None: webpack_cmd.append(f"--host={options.interface}") else: webpack_cmd.append("--host=0.0.0.0") - subprocess.Popen(webpack_cmd) + return subprocess.Popen(webpack_cmd) def transform_url(protocol: str, path: str, query: str, target_port: int, target_host: str) -> str: # generate url with target host @@ -362,15 +361,17 @@ def print_listeners() -> None: proxy_warning = f"Only the proxy port ({proxy_port}) is exposed." print(WARNING + "Note to Vagrant users: " + ENDC + proxy_warning + '\n') -if options.test: - do_one_time_webpack_compile() -else: - start_webpack_watcher() - -for cmd in server_processes(): - subprocess.Popen(cmd) +children = [] try: + if options.test: + do_one_time_webpack_compile() + else: + children.append(start_webpack_watcher()) + + for cmd in server_processes(): + children.append(subprocess.Popen(cmd)) + app = Application(enable_logging=options.enable_tornado_logging) try: app.listen(proxy_port, address=options.interface) @@ -385,12 +386,13 @@ try: for s in (signal.SIGINT, signal.SIGTERM): signal.signal(s, shutdown_handler) ioloop.start() -except Exception: - # Print the traceback before we get SIGTERM and die. - traceback.print_exc() - raise finally: - # Kill everything in our process group. - os.killpg(0, signal.SIGTERM) + for child in children: + child.terminate() + + print("Waiting for children to stop...") + for child in children: + child.wait() + # Remove pid file when development server closed correctly. os.remove(pid_file_path)