diff --git a/robyn/processpool.py b/robyn/processpool.py index e1ca456f3..cc302e089 100644 --- a/robyn/processpool.py +++ b/robyn/processpool.py @@ -51,9 +51,18 @@ def run_processes( ) def terminating_signal_handler(_sig, _frame): - logger.info("Terminating server!!", bold=True) + logger.info("Gracefully shutting down server...", bold=True) for process in process_pool: - process.kill() + process.terminate() + + for process in process_pool: + process.join(timeout=30) + if process.is_alive(): + logger.warning("Process %s did not shut down in time, forcing kill.", process.pid) + process.kill() + process.join(timeout=5) + + sys.exit(0) signal.signal(signal.SIGINT, terminating_signal_handler) signal.signal(signal.SIGTERM, terminating_signal_handler) @@ -220,6 +229,12 @@ def spawn_process( try: server.start(socket, workers) loop = asyncio.get_event_loop() + + if not sys.platform.startswith("win32"): + loop.add_signal_handler(signal.SIGTERM, loop.stop) + loop.run_forever() except KeyboardInterrupt: + pass + finally: loop.close() diff --git a/robyn/reloader.py b/robyn/reloader.py index 2139dfcbf..e89f2dff4 100644 --- a/robyn/reloader.py +++ b/robyn/reloader.py @@ -123,7 +123,13 @@ def __init__(self, file_path: str, directory_path: str) -> None: def stop_server(self) -> None: if self.process: - os.kill(self.process.pid, signal.SIGTERM) # Stop the subprocess using os.kill() + self.process.terminate() + try: + self.process.wait(timeout=5) + except subprocess.TimeoutExpired: + logger.warning("Process %s did not shut down in time, forcing kill.", self.process.pid) + self.process.kill() + self.process.wait() def reload(self) -> None: self.stop_server() @@ -138,10 +144,6 @@ def reload(self) -> None: clean_rust_binaries(self.built_rust_binaries) self.built_rust_binaries = compile_rust_files(self.directory_path) - prev_process = self.process - if prev_process: - prev_process.kill() - self.process = subprocess.Popen( [sys.executable, *arguments], env=new_env,