From ea0f93ac2416276961edbf49b93096a52b396211 Mon Sep 17 00:00:00 2001 From: Jendrik Seipp Date: Wed, 29 May 2024 17:08:19 +0200 Subject: [PATCH] [issue1138] Cleanly shut down the planner when it terminates. * Raise exception in exit_with() to ensure that destructors are called upon program exit. * Add and use non-reentrant report_exit_code() function. --- src/search/planner.cc | 72 ++++++++++++++++-------------- src/search/utils/system.cc | 17 ++++++- src/search/utils/system.h | 13 ++++++ src/search/utils/system_windows.cc | 13 ++---- 4 files changed, 70 insertions(+), 45 deletions(-) diff --git a/src/search/planner.cc b/src/search/planner.cc index e86ef8891f..a524825698 100644 --- a/src/search/planner.cc +++ b/src/search/planner.cc @@ -13,38 +13,44 @@ using namespace std; using utils::ExitCode; int main(int argc, const char **argv) { - utils::register_event_handlers(); - - if (argc < 2) { - utils::g_log << usage(argv[0]) << endl; - utils::exit_with(ExitCode::SEARCH_INPUT_ERROR); - } - - bool unit_cost = false; - if (static_cast(argv[1]) != "--help") { - utils::g_log << "reading input..." << endl; - tasks::read_root_task(cin); - utils::g_log << "done reading input!" << endl; - TaskProxy task_proxy(*tasks::g_root_task); - unit_cost = task_properties::is_unit_cost(task_proxy); + try { + utils::register_event_handlers(); + + if (argc < 2) { + utils::g_log << usage(argv[0]) << endl; + utils::exit_with(ExitCode::SEARCH_INPUT_ERROR); + } + + bool unit_cost = false; + if (static_cast(argv[1]) != "--help") { + utils::g_log << "reading input..." << endl; + tasks::read_root_task(cin); + utils::g_log << "done reading input!" << endl; + TaskProxy task_proxy(*tasks::g_root_task); + unit_cost = task_properties::is_unit_cost(task_proxy); + } + + shared_ptr search_algorithm = + parse_cmd_line(argc, argv, unit_cost); + + + utils::Timer search_timer; + search_algorithm->search(); + search_timer.stop(); + utils::g_timer.stop(); + + search_algorithm->save_plan_if_necessary(); + search_algorithm->print_statistics(); + utils::g_log << "Search time: " << search_timer << endl; + utils::g_log << "Total time: " << utils::g_timer << endl; + + ExitCode exitcode = search_algorithm->found_solution() + ? ExitCode::SUCCESS + : ExitCode::SEARCH_UNSOLVED_INCOMPLETE; + exit_with(exitcode); + } catch (const utils::ExitException &e) { + /* To ensure that all destructors are called before the program exits, + we raise an exception in utils::exit_with() and let main() return. */ + return static_cast(e.get_exitcode()); } - - shared_ptr search_algorithm = - parse_cmd_line(argc, argv, unit_cost); - - - utils::Timer search_timer; - search_algorithm->search(); - search_timer.stop(); - utils::g_timer.stop(); - - search_algorithm->save_plan_if_necessary(); - search_algorithm->print_statistics(); - utils::g_log << "Search time: " << search_timer << endl; - utils::g_log << "Total time: " << utils::g_timer << endl; - - ExitCode exitcode = search_algorithm->found_solution() - ? ExitCode::SUCCESS - : ExitCode::SEARCH_UNSOLVED_INCOMPLETE; - exit_with(exitcode); } diff --git a/src/search/utils/system.cc b/src/search/utils/system.cc index 001f68542a..46a2438908 100644 --- a/src/search/utils/system.cc +++ b/src/search/utils/system.cc @@ -44,9 +44,22 @@ bool is_exit_code_error_reentrant(ExitCode exitcode) { } } +void report_exit_code(ExitCode exitcode) { + const char *message = get_exit_code_message_reentrant(exitcode); + bool is_error = is_exit_code_error_reentrant(exitcode); + if (message) { + ostream &stream = is_error ? cerr : cout; + stream << message << endl; + } else { + cerr << "Exitcode: " << static_cast(exitcode) << endl + << "Unknown exitcode." << endl; + abort(); + } +} + void exit_with(ExitCode exitcode) { - report_exit_code_reentrant(exitcode); - exit(static_cast(exitcode)); + report_exit_code(exitcode); + throw ExitException(exitcode); } void exit_with_reentrant(ExitCode exitcode) { diff --git a/src/search/utils/system.h b/src/search/utils/system.h index 1f23ef19c7..9d5218afcb 100644 --- a/src/search/utils/system.h +++ b/src/search/utils/system.h @@ -53,6 +53,18 @@ enum class ExitCode { SEARCH_UNSUPPORTED = 34 }; +class ExitException : public std::exception { + ExitCode exitcode; +public: + explicit ExitException(ExitCode exitcode) + : exitcode(exitcode) { + } + + ExitCode get_exitcode() const { + return exitcode; + } +}; + NO_RETURN extern void exit_with(ExitCode returncode); NO_RETURN extern void exit_with_reentrant(ExitCode returncode); @@ -60,6 +72,7 @@ int get_peak_memory_in_kb(); const char *get_exit_code_message_reentrant(ExitCode exitcode); bool is_exit_code_error_reentrant(ExitCode exitcode); void register_event_handlers(); +void report_exit_code(ExitCode exitcode); void report_exit_code_reentrant(ExitCode exitcode); int get_process_id(); } diff --git a/src/search/utils/system_windows.cc b/src/search/utils/system_windows.cc index a244b68468..3fbe316d34 100644 --- a/src/search/utils/system_windows.cc +++ b/src/search/utils/system_windows.cc @@ -58,16 +58,9 @@ void register_event_handlers() { } void report_exit_code_reentrant(ExitCode exitcode) { - const char *message = get_exit_code_message_reentrant(exitcode); - bool is_error = is_exit_code_error_reentrant(exitcode); - if (message) { - ostream &stream = is_error ? cerr : cout; - stream << message << endl; - } else { - cerr << "Exitcode: " << static_cast(exitcode) << endl - << "Unknown exitcode." << endl; - abort(); - } + /* We call a function that uses ostreams even though this is unsafe in + reentrant code, because we don't know how to do it otherwise on Windows. */ + report_exit_code(exitcode); } int get_process_id() {