Path: blob/main/crates/bevy_app/src/terminal_ctrl_c_handler.rs
6595 views
use core::sync::atomic::{AtomicBool, Ordering};12use bevy_ecs::event::EventWriter;34use crate::{App, AppExit, Plugin, Update};56pub use ctrlc;78/// Indicates that all [`App`]'s should exit.9static SHOULD_EXIT: AtomicBool = AtomicBool::new(false);1011/// Gracefully handles `Ctrl+C` by emitting a [`AppExit`] event. This plugin is part of the `DefaultPlugins`.12///13/// ```no_run14/// # use bevy_app::{App, NoopPluginGroup as MinimalPlugins, PluginGroup, TerminalCtrlCHandlerPlugin};15/// fn main() {16/// App::new()17/// .add_plugins(MinimalPlugins)18/// .add_plugins(TerminalCtrlCHandlerPlugin)19/// .run();20/// }21/// ```22///23/// If you want to setup your own `Ctrl+C` handler, you should call the24/// [`TerminalCtrlCHandlerPlugin::gracefully_exit`] function in your handler if you want bevy to gracefully exit.25/// ```no_run26/// # use bevy_app::{App, NoopPluginGroup as DefaultPlugins, PluginGroup, TerminalCtrlCHandlerPlugin, ctrlc};27/// fn main() {28/// // Your own `Ctrl+C` handler29/// ctrlc::set_handler(move || {30/// // Other clean up code ...31///32/// TerminalCtrlCHandlerPlugin::gracefully_exit();33/// });34///35/// App::new()36/// .add_plugins(DefaultPlugins)37/// .run();38/// }39/// ```40#[derive(Default)]41pub struct TerminalCtrlCHandlerPlugin;4243impl TerminalCtrlCHandlerPlugin {44/// Sends the [`AppExit`] event to all apps using this plugin to make them gracefully exit.45pub fn gracefully_exit() {46SHOULD_EXIT.store(true, Ordering::Relaxed);47}4849/// Sends a [`AppExit`] event when the user presses `Ctrl+C` on the terminal.50pub fn exit_on_flag(mut events: EventWriter<AppExit>) {51if SHOULD_EXIT.load(Ordering::Relaxed) {52events.write(AppExit::from_code(130));53}54}55}5657impl Plugin for TerminalCtrlCHandlerPlugin {58fn build(&self, app: &mut App) {59let result = ctrlc::try_set_handler(move || {60Self::gracefully_exit();61});62match result {63Ok(()) => {}64Err(ctrlc::Error::MultipleHandlers) => {65log::info!("Skipping installing `Ctrl+C` handler as one was already installed. Please call `TerminalCtrlCHandlerPlugin::gracefully_exit` in your own `Ctrl+C` handler if you want Bevy to gracefully exit on `Ctrl+C`.");66}67Err(err) => log::warn!("Failed to set `Ctrl+C` handler: {err}"),68}6970app.add_systems(Update, TerminalCtrlCHandlerPlugin::exit_on_flag);71}72}737475