Skip to content

dx serve does not gracefully shutdown server on windows #5157

@jaysonmaw

Description

@jaysonmaw

Problem

Setting a Ctrl-C handler is ignored when run from dx serve despite working when running directly.

fn soft_kill(&mut self) on windows is just calling taskkill which provides no meaningful way to detect a graceful shutdown. This is a problem for apps that want to flush data to disk on shutdown. fn soft_kill(&mut self)'s docs state that it attempts to "Gracefully kill the process and all of its children" but that does not seem to be the case.

Why taskill command even without /F does not trigger graceful shutdown

According to docs taskkill without /F sends a WM_CLOSE message to the target program's window, however console applications don't have a window to target so no graceful shutdown is trigged. taskkill does not send CTRL_C_EVENT or any other signal that can be caught by a console application.
There is actually a hint that this is going on in dx serve as well, as if you look at the console output when hitting Ctrl-C you will see the following logs being output from taskkill:
ERROR: The process with PID #### could not be terminated. This process can only be terminated forcefully (with /F option)
This happens because it realizes it is unable to send the WM_CLOSE message so gives up with that error message.

Steps To Reproduce

Steps to reproduce the behavior:

  • Setup Ctrl-C Handler that calls some sort of graceful shutdown behavior.
  • Run app using dx serve --platform web
  • Hit Ctrl-C in the console window
  • Observe that your Ctrl-C Handler is not triggered

Expected behavior

Hitting Ctrl-C while running dx serve would forward the Ctrl-C event to the child process.

Screenshots

N/A

Environment:

  • Dx version: 0.7.2-35351eb
  • Rust version: rustc 1.94.0-nightly
  • OS info: Windows 11
  • App platform: web

Possible Solution

Just include the send_ctrlc crate in the dx cli crate, and then use the provided fn terminate(&mut self) now callable on a tokio::process::Child which is what dx serve holds currently. This send's a CTRL_BREAK_EVENT on windows and SIGTERM on unix. CTRL_BREAK_EVENT is in fact handled as a Crtl-C in the popular handler crates.

If this solution is acceptable I can open a PR as well if needed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions