Rust-SDL2 / rust-sdl2

SDL2 bindings for Rust
MIT License
2.71k stars 466 forks source link

Ability to prevent catching SIGINT so that CTRL+C doesn't invoke SDL_QUIT event #769

Open polarathene opened 6 years ago

polarathene commented 6 years ago

Trying to differentiate between the closing of the SDL window vs Ctrl+C in the terminal window terminating the running process. It seems SDL catches SIGINT and treats it as a SDL_QUIT event? I came across a hint that should prevent this behaviour but it does not seem to have any effect if declared before or after sdl2::init().

RustSDL2 sd;::hint::set() SDL Wiki - SDL_HINT_NO_SIGNAL_HANDLERS

sdl2::hint::set("SDL_HINT_NO_SIGNAL_HANDLERS", "1");

Seems to be related to this old issue: https://github.com/Rust-SDL2/rust-sdl2/issues/488

There is a C example here, it seems to declare before init. I'm not quite sure how to invoke that based on the crate docs for the sdl2_sys extern method, or if it would work any better than using the API like shared above.

Cobrand commented 6 years ago

I didn't try on my machine but setting the hint before the init should work.

The "hint::set" function returns a boolean, what does it return for you? It should return "true" if it has been properly set. Maybe you can tinker with priorities as well, it may help.

Cobrand commented 6 years ago

By the way, do you have something to override rust's CTRL-C handler? By default it runs all destructors (I think) and kills threads, children processes, ...

Make sure this is an issue with SDL2 and not Rust itself, it may save you some time :)

polarathene commented 6 years ago

Make sure this is an issue with SDL2 and not Rust itself, it may save you some time :)

Well SDL2 requires we use the event pump loop right? In that I have SDL_QUIT event for breaking the loop, I also have an escape key for doing the same. If I have the SDL_QUIT event just perform a println!() instead of breaking the loop, then when I close the app window via X button or if I go to the terminal and press Ctrl+C it's caught as SDL_QUIT and just prints the string to stdout.. Only the escape key works.

By the way, do you have something to override rust's CTRL-C handler?

I had tried this with ctrlc crate, if I used that pressing ctrl+c will have the same effect as mentioned above. Although if I press escape key, it will gracefully exit the program like the ctrlc crate example shows, but first that SDL loop has to be broken. In regular Rust code without SDL, there is no SDL_Event, Ctrl+C would just break out of that loop and terminate the program or gracefully exit with ctrlc crate.

The "hint::set" function returns a boolean, what does it return for you? It should return "true" if it has been properly set. Maybe you can tinker with priorities as well, it may help.

Yes it returns true. I haven't tried priorities yet. It'd be helpful if anyone else can confirm that SDL still catches SIGINT and converts to SDL_QUIT event. I have seen some approaches to use libc directly to fix this, though I'd rather avoid that if possible.

michaelfairley commented 6 years ago

Somewhat confusingly, the hint string is SDL_NO_SIGNAL_HANDLERS, not SDL_HINT_NO_SIGNAL_HANDLERS. I've successfully used this to suppress the SDL_QUIT event when I Ctrl-C a test application.

@Cobrand: it seems like bindgen might have a way to expose those defines in rust; that might be helpful for avoiding these sorts of mixups?

michaelfairley commented 6 years ago
pub const SDL_HINT_NO_SIGNAL_HANDLERS: &'static [u8; 23usize] =
    b"SDL_NO_SIGNAL_HANDLERS\x00";

already appears in the bindgen output for sdl2-sys, but I can't immediately think of a nice way to make that usable in the wrapper, especially with the current API.