Thread the parser into process_clean_after_marking

This commit is contained in:
ridiculousfish 2019-04-29 20:58:58 -07:00
parent 32d1b3d7cb
commit 9fb98baba6
9 changed files with 29 additions and 23 deletions

View file

@ -64,14 +64,14 @@ static bool any_jobs_finished(size_t jobs_len) {
return false; return false;
} }
static int wait_for_backgrounds(bool any_flag) { static int wait_for_backgrounds(parser_t &parser, bool any_flag) {
size_t jobs_len = jobs().size(); size_t jobs_len = jobs().size();
while ((!any_flag && !all_jobs_finished()) || (any_flag && !any_jobs_finished(jobs_len))) { while ((!any_flag && !all_jobs_finished()) || (any_flag && !any_jobs_finished(jobs_len))) {
if (reader_test_interrupted()) { if (reader_test_interrupted()) {
return 128 + SIGINT; return 128 + SIGINT;
} }
proc_wait_any(); proc_wait_any(parser);
} }
return 0; return 0;
} }
@ -104,13 +104,14 @@ static bool any_specified_jobs_finished(const std::vector<job_id_t> &ids) {
return false; return false;
} }
static int wait_for_backgrounds_specified(const std::vector<job_id_t> &ids, bool any_flag) { static int wait_for_backgrounds_specified(parser_t &parser, const std::vector<job_id_t> &ids,
bool any_flag) {
while ((!any_flag && !all_specified_jobs_finished(ids)) || while ((!any_flag && !all_specified_jobs_finished(ids)) ||
(any_flag && !any_specified_jobs_finished(ids))) { (any_flag && !any_specified_jobs_finished(ids))) {
if (reader_test_interrupted()) { if (reader_test_interrupted()) {
return 128 + SIGINT; return 128 + SIGINT;
} }
proc_wait_any(); proc_wait_any(parser);
} }
return 0; return 0;
} }
@ -204,7 +205,7 @@ int builtin_wait(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
if (w.woptind == argc) { if (w.woptind == argc) {
// no jobs specified // no jobs specified
retval = wait_for_backgrounds(any_flag); retval = wait_for_backgrounds(parser, any_flag);
} else { } else {
// jobs specified // jobs specified
std::vector<job_id_t> waited_job_ids; std::vector<job_id_t> waited_job_ids;
@ -236,7 +237,7 @@ int builtin_wait(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
if (waited_job_ids.empty()) return STATUS_INVALID_ARGS; if (waited_job_ids.empty()) return STATUS_INVALID_ARGS;
retval = wait_for_backgrounds_specified(waited_job_ids, any_flag); retval = wait_for_backgrounds_specified(parser, waited_job_ids, any_flag);
} }
return retval; return retval;

View file

@ -286,7 +286,7 @@ void internal_exec_helper(parser_t &parser, parsed_source_ref_t parsed_source, t
morphed_chain.clear(); morphed_chain.clear();
io_cleanup_fds(opened_fds); io_cleanup_fds(opened_fds);
job_reap(false); job_reap(parser, false);
} }
// Returns whether we can use posix spawn for a given process in a given job. // Returns whether we can use posix spawn for a given process in a given job.

View file

@ -253,7 +253,8 @@ static maybe_t<char_event_t> interrupt_handler() {
// Fire any pending events. // Fire any pending events.
event_fire_delayed(); event_fire_delayed();
// Reap stray processes, including printing exit status messages. // Reap stray processes, including printing exit status messages.
if (job_reap(true)) reader_repaint_needed(); // TODO: shouldn't need this parser here.
if (job_reap(parser_t::principal_parser(), true)) reader_repaint_needed();
// Tell the reader an event occured. // Tell the reader an event occured.
if (reader_reading_interrupted()) { if (reader_reading_interrupted()) {
auto vintr = shell_modes.c_cc[VINTR]; auto vintr = shell_modes.c_cc[VINTR];

View file

@ -1294,7 +1294,7 @@ parse_execution_result_t parse_execution_context_t::run_1_job(tnode_t<g::job> jo
profile_item->skipped = !populated_job; profile_item->skipped = !populated_job;
} }
job_reap(false); // clean up jobs job_reap(*parser, false); // clean up jobs
return populated_job ? parse_execution_success : parse_execution_errored; return populated_job ? parse_execution_success : parse_execution_errored;
} }

View file

@ -670,7 +670,7 @@ int parser_t::eval_node(parsed_source_ref_t ps, tnode_t<T> node, const io_chain_
return 1; return 1;
} }
job_reap(false); // not sure why we reap jobs here job_reap(*this, false); // not sure why we reap jobs here
// Start it up // Start it up
scope_block_t *scope_block = this->push_block<scope_block_t>(block_type); scope_block_t *scope_block = this->push_block<scope_block_t>(block_type);
@ -683,7 +683,7 @@ int parser_t::eval_node(parsed_source_ref_t ps, tnode_t<T> node, const io_chain_
exc.restore(); exc.restore();
this->pop_block(scope_block); this->pop_block(scope_block);
job_reap(false); // reap again job_reap(*this, false); // reap again
return result; return result;
} }

View file

@ -157,6 +157,9 @@ struct library_data_t {
/// Number of recursive calls to builtin_complete(). /// Number of recursive calls to builtin_complete().
uint32_t builtin_complete_recursion_level{0}; uint32_t builtin_complete_recursion_level{0};
/// Whether we are currently cleaning processes.
bool is_cleaning_procs{false};
}; };
class parser_t : public std::enable_shared_from_this<parser_t> { class parser_t : public std::enable_shared_from_this<parser_t> {

View file

@ -551,16 +551,17 @@ static bool job_wants_message(const shared_ptr<job_t> &j, bool print_for_foregro
/// Remove completed jobs from the job list, printing status messages as appropriate. /// Remove completed jobs from the job list, printing status messages as appropriate.
/// \return whether something was printed. /// \return whether something was printed.
static bool process_clean_after_marking(bool allow_interactive) { static bool process_clean_after_marking(parser_t &parser, bool allow_interactive) {
ASSERT_IS_MAIN_THREAD(); ASSERT_IS_MAIN_THREAD();
bool printed = false; bool printed = false;
// This function may fire an event handler, we do not want to call ourselves recursively (to // This function may fire an event handler, we do not want to call ourselves recursively (to
// avoid infinite recursion). // avoid infinite recursion).
static std::atomic<bool> locked { false }; if (parser.libdata().is_cleaning_procs) {
if (locked.exchange(true, std::memory_order::memory_order_relaxed)) {
return false; return false;
} }
parser.libdata().is_cleaning_procs = true;
const cleanup_t cleanup([&] { parser.libdata().is_cleaning_procs = false; });
// This may be invoked in an exit handler, after the TERM has been torn down // This may be invoked in an exit handler, after the TERM has been torn down
// Don't try to print in that case (#3222) // Don't try to print in that case (#3222)
@ -628,18 +629,17 @@ static bool process_clean_after_marking(bool allow_interactive) {
fflush(stdout); fflush(stdout);
} }
locked = false;
return printed; return printed;
} }
bool job_reap(bool allow_interactive) { bool job_reap(parser_t &parser, bool allow_interactive) {
ASSERT_IS_MAIN_THREAD(); ASSERT_IS_MAIN_THREAD();
process_mark_finished_children(false); process_mark_finished_children(false);
// Preserve the exit status. // Preserve the exit status.
auto saved_statuses = proc_get_last_statuses(); auto saved_statuses = proc_get_last_statuses();
bool printed = process_clean_after_marking(allow_interactive); bool printed = process_clean_after_marking(parser, allow_interactive);
// Restore the exit status. // Restore the exit status.
proc_set_last_statuses(std::move(saved_statuses)); proc_set_last_statuses(std::move(saved_statuses));
@ -970,10 +970,10 @@ void proc_pop_interactive() {
if (is_interactive != old) signal_set_handlers(); if (is_interactive != old) signal_set_handlers();
} }
void proc_wait_any() { void proc_wait_any(parser_t &parser) {
ASSERT_IS_MAIN_THREAD(); ASSERT_IS_MAIN_THREAD();
process_mark_finished_children(true /* block_ok */); process_mark_finished_children(true /* block_ok */);
process_clean_after_marking(is_interactive); process_clean_after_marking(parser, is_interactive);
} }
void hup_background_jobs() { void hup_background_jobs() {

View file

@ -483,9 +483,10 @@ int proc_get_last_status();
statuses_t proc_get_last_statuses(); statuses_t proc_get_last_statuses();
/// Notify the user about stopped or terminated jobs, and delete completed jobs from the job list. /// Notify the user about stopped or terminated jobs, and delete completed jobs from the job list.
/// If \p interactive is set, allow reaping interactive jobs; otherwise skip them. /// If \p interactive is set, allow removing interactive jobs; otherwise skip them.
/// \return whether text was printed to stdout. /// \return whether text was printed to stdout.
bool job_reap(bool interactive); class parser_t;
bool job_reap(parser_t &parser, bool interactive);
/// Mark a process as failed to execute (and therefore completed). /// Mark a process as failed to execute (and therefore completed).
void job_mark_process_as_failed(const std::shared_ptr<job_t> &job, const process_t *p); void job_mark_process_as_failed(const std::shared_ptr<job_t> &job, const process_t *p);
@ -518,7 +519,7 @@ void proc_push_interactive(int value);
void proc_pop_interactive(); void proc_pop_interactive();
/// Wait for any process finishing, or receipt of a signal. /// Wait for any process finishing, or receipt of a signal.
void proc_wait_any(); void proc_wait_any(parser_t &parser);
/// Set and get whether we are in initialization. /// Set and get whether we are in initialization.
// Hackish. In order to correctly report the origin of code with no associated file, we need to // Hackish. In order to correctly report the origin of code with no associated file, we need to

View file

@ -1961,7 +1961,7 @@ void reader_run_command(parser_t &parser, const wcstring &cmd) {
gettimeofday(&time_before, NULL); gettimeofday(&time_before, NULL);
parser.eval(cmd, io_chain_t(), TOP); parser.eval(cmd, io_chain_t(), TOP);
job_reap(true); job_reap(parser, true);
gettimeofday(&time_after, NULL); gettimeofday(&time_after, NULL);