From 9870cf838afd71abdfe66db6589f663c7d240852 Mon Sep 17 00:00:00 2001 From: Kurtis Rader Date: Mon, 19 Dec 2016 20:35:57 -0800 Subject: [PATCH] fix exiting `breakpoint` interactive context Commit 8d27f81a to change how background jobs are handled (killed rather than left running) when the shell is exited did not correctly handle the nested interactive context created by the `breakpoint` command. This fixes that mistake. Now any background jobs that already existed, or were created within the `breakpoint` context, are left running when exiting that context. --- src/reader.cpp | 63 ++++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/src/reader.cpp b/src/reader.cpp index 76bfab921..49f4226af 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -14,29 +14,30 @@ #include "config.h" // IWYU pragma: no_include +#include #include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #ifdef HAVE_SIGINFO_H #include #endif +#include +#include +#include +#include #ifdef HAVE_SYS_SELECT_H #include #endif -#include -#include -#include +#include #include +#include +#include +#include #include +#include + +#include +#include #include #include "color.h" @@ -2222,17 +2223,18 @@ bool shell_is_exiting() { /// This function is called when the main loop notices that end_loop has been set while in /// interactive mode. It checks if it is ok to exit. static void handle_end_loop() { - bool bg_jobs = false; - bool is_breakpoint = false; - const parser_t &parser = parser_t::principal_parser(); - - for (size_t i = 0; i < parser.block_count(); i++) { - if (parser.block_at_index(i)->type() == BREAKPOINT) { - is_breakpoint = true; - break; + if (!reader_exit_forced()) { + const parser_t &parser = parser_t::principal_parser(); + for (size_t i = 0; i < parser.block_count(); i++) { + if (parser.block_at_index(i)->type() == BREAKPOINT) { + // We're executing within a breakpoint so we do not want to terminate the shell and + // kill background jobs. + return; + } } } + bool bg_jobs = false; job_iterator_t jobs; while (job_t *j = jobs.next()) { if (!job_is_completed(j)) { @@ -2241,19 +2243,20 @@ static void handle_end_loop() { } } - if (!reader_exit_forced() && !data->prev_end_loop && bg_jobs && !is_breakpoint) { + if (!data->prev_end_loop && bg_jobs) { writestr(_(L"There are stopped or running jobs.\n")); writestr(_(L"A second attempt to exit will force their termination.\n")); reader_exit(0, 0); data->prev_end_loop = 1; - } else { - // Kill background jobs. - job_iterator_t jobs; - while (job_t *j = jobs.next()) { - if (!job_is_completed(j)) { - if (job_is_stopped(j)) job_signal(j, SIGCONT); - job_signal(j, SIGHUP); - } + return; + } + + // Kill background jobs before exiting. + jobs.reset(); + while (job_t *j = jobs.next()) { + if (!job_is_completed(j)) { + if (job_is_stopped(j)) job_signal(j, SIGCONT); + job_signal(j, SIGHUP); } } }