diff --git a/src/common.cpp b/src/common.cpp index b5d2a8bde..ccdcd29ef 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -78,6 +78,7 @@ static void debug_shared(const wchar_t msg_level, const wcstring &msg); const wcstring whitespace = L" \t\r\n\v"; const char *whitespace_narrow = " \t\r\n\v"; +std::stack> before_exit; bool is_whitespace(const wchar_t input) { for (auto c : whitespace) { diff --git a/src/common.h b/src/common.h index f3832bb8b..bb07c1435 100644 --- a/src/common.h +++ b/src/common.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -423,6 +424,8 @@ void assert_is_background_thread(const char *who); #define ASSERT_IS_BACKGROUND_THREAD_TRAMPOLINE(x) assert_is_background_thread(x) #define ASSERT_IS_BACKGROUND_THREAD() ASSERT_IS_BACKGROUND_THREAD_TRAMPOLINE(__FUNCTION__) +extern std::stack> before_exit; + // fish_mutex is a wrapper around std::mutex that tracks whether it is locked, allowing for checking // if the mutex is locked. It owns a boolean guarded by the lock that records whether the lock is // currently locked; this is only used by assertions for correctness. diff --git a/src/exec.cpp b/src/exec.cpp index 957c7fbb1..2cc046044 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -359,6 +359,12 @@ static bool can_use_posix_spawn_for_job(const job_t *job, const process_t *proce void internal_exec(job_t *j, const io_chain_t &&all_ios) { // Do a regular launch - but without forking first... + // since we are about to quit, make sure to run pending cleanup tasks + while (!before_exit.empty()) { + before_exit.top()(); + before_exit.pop(); + } + // setup_child_process makes sure signals are properly set up. // PCA This is for handling exec. Passing all_ios here matches what fish 2.0.0 and 1.x did. diff --git a/src/fish.cpp b/src/fish.cpp index baeab0dd0..2580a38ad 100644 --- a/src/fish.cpp +++ b/src/fish.cpp @@ -466,6 +466,12 @@ int main(int argc, char **argv) { parser.emit_profiling(s_profiling_output_filename); } + // since we exit without destructors, we need some way to run cleanup code when necessary + while (!before_exit.empty()) { + before_exit.top()(); + before_exit.pop(); + } + history_save_all(); proc_destroy(); exit_without_destructors(exit_status);