Skip to content

Commit

Permalink
Fix CTRL_CLOSE, CTRL_LOGOFF and CTRL_SHUTDOWN on windows killing the …
Browse files Browse the repository at this point in the history
…program before it had the chance to react
  • Loading branch information
Finomnis committed Jan 25, 2025
1 parent ee19b0e commit 6e60886
Showing 1 changed file with 24 additions and 1 deletion.
25 changes: 24 additions & 1 deletion tokio/src/signal/windows/sys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,21 @@ fn new(signum: u32) -> io::Result<RxFuture> {
Ok(RxFuture::new(rx))
}

fn event_requires_infinite_sleep_in_handler(signum: u32) -> bool {
// Returning from the handler function of those events immediately terminates the process.
// So for async systems, the easiest solution is to simply never return from
// the handler function.
//
// For more information, see:
// https://learn.microsoft.com/en-us/windows/console/handlerroutine#remarks
match signum {
console::CTRL_CLOSE_EVENT => true,
console::CTRL_LOGOFF_EVENT => true,
console::CTRL_SHUTDOWN_EVENT => true,
_ => false,
}
}

#[derive(Debug)]
pub(crate) struct OsStorage {
ctrl_break: EventInfo,
Expand Down Expand Up @@ -114,13 +129,21 @@ unsafe extern "system" fn handler(ty: u32) -> BOOL {
// the handler routine is always invoked in a new thread, thus we don't
// have the same restrictions as in Unix signal handlers, meaning we can
// go ahead and perform the broadcast here.
if globals.broadcast() {
let result = if globals.broadcast() {
1
} else {
// No one is listening for this notification any more
// let the OS fire the next (possibly the default) handler.
0
};

if event_requires_infinite_sleep_in_handler(ty) {
loop {
std::thread::sleep(std::time::Duration::MAX);
}
}

result
}

#[cfg(all(test, not(loom)))]
Expand Down

0 comments on commit 6e60886

Please sign in to comment.