Skip to content

Commit

Permalink
Merge pull request #75999 from andrei8l/better-quit
Browse files Browse the repository at this point in the history
main: properly handle SIGINT
  • Loading branch information
dseguin authored Oct 21, 2024
2 parents d5265ca + e436583 commit ec2416a
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 34 deletions.
3 changes: 3 additions & 0 deletions src/do_turn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ namespace turn_handler
bool cleanup_at_end()
{
avatar &u = get_avatar();
if( g->uquit == QUIT_EXIT ) {
return true;
}
if( g->uquit == QUIT_DIED || g->uquit == QUIT_SUICIDE ) {
// Put (non-hallucinations) into the overmap so they are not lost.
for( monster &critter : g->all_monsters() ) {
Expand Down
4 changes: 4 additions & 0 deletions src/flexbuffer_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "cata_unreachable.h"
#include "filesystem.h"
#include "game.h"
#include "json.h"

namespace
Expand Down Expand Up @@ -252,6 +253,9 @@ bool JsonValue::read( std::string &s, bool throw_on_error ) const
void JsonObject::report_unvisited() const
{
#ifndef CATA_IN_TOOL
if( g && g->uquit == quit_status::QUIT_EXIT ) {
return;
}
if( !std::uncaught_exceptions() && report_unvisited_members && !visited_fields_bitset_.all() ) {
std::vector<size_t> skipped_members;
skipped_members.reserve( visited_fields_bitset_.size() );
Expand Down
19 changes: 19 additions & 0 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2800,8 +2800,27 @@ bool game::try_get_right_click_action( action_id &act, const tripoint_bub_ms &mo
return true;
}

bool game::query_exit_to_OS()
{
const int old_timeout = inp_mngr.get_timeout();
inp_mngr.reset_timeout();
uquit = QUIT_EXIT_PENDING; // change it before query so input_context doesn't get confused
if( query_yn( _( "Really Quit? All unsaved changes will be lost." ) ) ) {
uquit = QUIT_EXIT;
throw exit_exception();
}
uquit = QUIT_NO;
inp_mngr.set_timeout( old_timeout );
ui_manager::redraw_invalidated();
catacurses::doupdate();
return false;
}

bool game::is_game_over()
{
if( uquit == QUIT_EXIT ) {
return query_exit_to_OS();
}
if( uquit == QUIT_DIED || uquit == QUIT_WATCH ) {
Creature *player_killer = u.get_killer();
if( player_killer && player_killer->as_character() ) {
Expand Down
4 changes: 4 additions & 0 deletions src/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ enum quit_status {
QUIT_NOSAVED, // Quit without saving
QUIT_DIED, // Actual death
QUIT_WATCH, // Died, and watching aftermath
QUIT_EXIT, // Skip main menu and quit directly to OS
QUIT_EXIT_PENDING, // same as above, used temporarily so input_context doesn't get confused
};

enum safe_mode_type {
Expand Down Expand Up @@ -1033,6 +1035,8 @@ class game
void bury_screen() const;// Bury a dead character (record their last words)
void death_screen(); // Display our stats, "GAME OVER BOO HOO"
public:
bool query_exit_to_OS();
class exit_exception: public std::exception {};
/**
* If there is a robot (that can be disabled), query the player
* and try to disable it.
Expand Down
7 changes: 7 additions & 0 deletions src/handle_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,9 @@ input_context game::get_player_input( std::string &action )

creature_tracker &creatures = get_creature_tracker();
do {
if( g->uquit == QUIT_EXIT ) {
break;
}
if( bWeatherEffect && get_option<bool>( "ANIMATION_RAIN" ) ) {
/*
Location to add rain drop animation bits! Since it refreshes w_terrain it can be added to the animation section easily
Expand Down Expand Up @@ -3099,6 +3102,10 @@ bool game::handle_action()
// of location clicked.
std::optional<tripoint_bub_ms> mouse_target;

if( uquit == QUIT_EXIT ) {
return false;
}

if( uquit == QUIT_WATCH && action == "QUIT" ) {
uquit = QUIT_DIED;
return false;
Expand Down
20 changes: 20 additions & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "field_type.h"
#include "filesystem.h"
#include "flag.h"
#include "game.h"
#include "gates.h"
#include "harvest.h"
#include "input.h"
Expand Down Expand Up @@ -102,6 +103,7 @@
#include "translations.h"
#include "trap.h"
#include "type_id.h"
#include "ui_manager.h"
#include "veh_type.h"
#include "vehicle_group.h"
#include "vitamin.h"
Expand All @@ -123,6 +125,20 @@ DynamicDataLoader &DynamicDataLoader::get_instance()
return theDynamicDataLoader;
}

namespace
{

void check_sigint()
{
if( g && g->uquit == quit_status::QUIT_EXIT ) {
if( g->query_exit_to_OS() ) {
throw game::exit_exception();
}
}
}

} // namespace

void DynamicDataLoader::load_object( const JsonObject &jo, const std::string &src,
const cata_path &base_path,
const cata_path &full_path )
Expand Down Expand Up @@ -172,6 +188,7 @@ void DynamicDataLoader::load_deferred( deferred_json &data )
}
++it;
inp_mngr.pump_events();
check_sigint();
}
data.erase( data.begin(), it );
if( data.size() == n ) {
Expand Down Expand Up @@ -613,6 +630,7 @@ void DynamicDataLoader::load_all_from_json( const JsonValue &jsin, const std::st
// find type and dispatch each object until array close
for( JsonObject jo : ja ) {
load_object( jo, src, base_path, full_path );
check_sigint();
}
} else {
// not an object or an array?
Expand Down Expand Up @@ -842,6 +860,7 @@ void DynamicDataLoader::finalize_loaded_data()
for( const named_entry &e : entries ) {
loading_ui::show( _( "Finalizing" ), e.first );
e.second();
check_sigint();
}

if( !get_option<bool>( "SKIP_VERIFICATION" ) ) {
Expand Down Expand Up @@ -946,5 +965,6 @@ void DynamicDataLoader::check_consistency()
for( const named_entry &e : entries ) {
loading_ui::show( _( "Verifying" ), e.first );
e.second();
check_sigint();
}
}
5 changes: 5 additions & 0 deletions src/input_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ static const std::string ANY_INPUT = "ANY_INPUT";
static const std::string HELP_KEYBINDINGS = "HELP_KEYBINDINGS";
static const std::string COORDINATE = "COORDINATE";
static const std::string TIMEOUT = "TIMEOUT";
static const std::string QUIT = "QUIT";

const std::string &input_context::input_to_action( const input_event &inp ) const
{
Expand Down Expand Up @@ -445,6 +446,10 @@ const std::string &input_context::handle_input( const int timeout )
break;
}

if( g->uquit == QUIT_EXIT ) {
result = &QUIT;
break;
}
const std::string &action = input_to_action( next_action );

//Special global key to toggle language to english and back
Expand Down
54 changes: 23 additions & 31 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,42 +143,30 @@ namespace
// Used only if AttachConsole() works
FILE *CONOUT;
#endif
void exit_handler( int s )

#if !defined(_WIN32)
extern "C" void sigint_handler( int /* s */ )
{
if( g->uquit != QUIT_EXIT_PENDING ) {
g->uquit = QUIT_EXIT;
}
}
#endif

void exit_handler( int /* s */ )
{
const int old_timeout = inp_mngr.get_timeout();
inp_mngr.reset_timeout();
if( s != 2 || query_yn( _( "Really Quit? All unsaved changes will be lost." ) ) ) {
deinitDebug();
deinitDebug();

int exit_status = 0;
g.reset();
g.reset();

catacurses::endwin();
catacurses::endwin();

#if defined(__ANDROID__)
// Avoid capturing SIGABRT on exit on Android in crash report
// Can be removed once the SIGABRT on exit problem is fixed
signal( SIGABRT, SIG_DFL );
// Avoid capturing SIGABRT on exit on Android in crash report
// Can be removed once the SIGABRT on exit problem is fixed
signal( SIGABRT, SIG_DFL );
#endif

#if !defined(_WIN32)
if( s == 2 ) {
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = SIG_DFL;
sigemptyset( &sigIntHandler.sa_mask );
sigIntHandler.sa_flags = 0;
sigaction( SIGINT, &sigIntHandler, nullptr );
kill( getpid(), s );
} else
#endif
{
imclient.reset();
exit( exit_status );
}
}
inp_mngr.set_timeout( old_timeout );
ui_manager::redraw_invalidated();
catacurses::doupdate();
}

struct arg_handler {
Expand Down Expand Up @@ -836,7 +824,7 @@ int main( int argc, const char *argv[] )

#if !defined(_WIN32)
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = exit_handler;
sigIntHandler.sa_handler = sigint_handler;
sigemptyset( &sigIntHandler.sa_mask );
sigIntHandler.sa_flags = 0;
sigaction( SIGINT, &sigIntHandler, nullptr );
Expand Down Expand Up @@ -870,7 +858,11 @@ int main( int argc, const char *argv[] )

shared_ptr_fast<ui_adaptor> ui = g->create_or_get_main_ui_adaptor();
get_event_bus().send<event_type::game_begin>( getVersionString() );
while( !do_turn() ) {}
try {
while( !do_turn() ) { }
} catch( game::exit_exception const &/* ex */ ) {
break;
}
}

exit_handler( -999 );
Expand Down
9 changes: 9 additions & 0 deletions src/main_menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,10 @@ bool main_menu::opening_screen()
#endif

while( !start ) {
if( g->uquit == QUIT_EXIT ) {
return false;
}

ui_manager::redraw();
std::string action = ctxt.handle_input();
input_event sInput = ctxt.get_raw_input();
Expand Down Expand Up @@ -795,9 +799,12 @@ bool main_menu::opening_screen()
// also check special keys
if( action == "QUIT" ) {
#if !defined(EMSCRIPTEN)
g->uquit = QUIT_EXIT_PENDING;
if( query_yn( _( "Really quit?" ) ) ) {
g->uquit = QUIT_EXIT;
return false;
}
g->uquit = QUIT_NO;
#endif
} else if( action == "LEFT" || action == "PREV_TAB" || action == "RIGHT" || action == "NEXT_TAB" ) {
sel_line = 0;
Expand Down Expand Up @@ -1110,6 +1117,8 @@ bool main_menu::load_game( std::string const &worldname, save_t const &savegame

try {
g->setup();
} catch( game::exit_exception const &/* ex */ ) {
return false;
} catch( const std::exception &err ) {
debugmsg( "Error: %s", err.what() );
return false;
Expand Down
5 changes: 3 additions & 2 deletions src/sdltiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3522,8 +3522,9 @@ static void CheckMessages()
try_sdl_update();
}
if( quit ) {
catacurses::endwin();
exit( 0 );
if( g->uquit != quit_status::QUIT_EXIT_PENDING ) {
g->uquit = quit_status::QUIT_EXIT;
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1028,7 +1028,8 @@ void uilist::query( bool loop, int timeout, bool allow_unfiltered_hotkeys )
if( entries[ selected ].enabled || allow_disabled ) {
ret = entries[selected].retval;
}
} else if( allow_cancel && ret_act == "UILIST.QUIT" ) {
} else if( ( allow_cancel && ret_act == "UILIST.QUIT" ) ||
( g->uquit == QUIT_EXIT && ret_act == "QUIT" ) ) {
ret = UILIST_CANCEL;
} else if( ret_act == "TIMEOUT" ) {
ret = UILIST_WAIT_INPUT;
Expand Down

0 comments on commit ec2416a

Please sign in to comment.