mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-28 13:53:10 +00:00
Eliminate the global jobs() function
All job lists are attached to a parser now.
This commit is contained in:
parent
afff93bdb2
commit
8a8b2513b5
17 changed files with 79 additions and 117 deletions
|
@ -12,6 +12,7 @@
|
|||
#include "common.h"
|
||||
#include "fallback.h" // IWYU pragma: keep
|
||||
#include "io.h"
|
||||
#include "parser.h"
|
||||
#include "proc.h"
|
||||
#include "wutil.h" // IWYU pragma: keep
|
||||
|
||||
|
@ -28,9 +29,9 @@ static int send_to_bg(parser_t &parser, io_streams_t &streams, job_t *j) {
|
|||
|
||||
streams.err.append_format(_(L"Send job %d '%ls' to background\n"), j->job_id,
|
||||
j->command_wcstr());
|
||||
j->promote();
|
||||
parser.job_promote(j);
|
||||
j->set_flag(job_flag_t::FOREGROUND, false);
|
||||
j->continue_job(true, j->is_stopped());
|
||||
j->continue_job(parser, true, j->is_stopped());
|
||||
return STATUS_CMD_OK;
|
||||
}
|
||||
|
||||
|
@ -52,7 +53,7 @@ int builtin_bg(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
|||
if (optind == argc) {
|
||||
// No jobs were specified so use the most recent (i.e., last) job.
|
||||
job_t *job = nullptr;
|
||||
for (const auto &j : jobs()) {
|
||||
for (const auto &j : parser.jobs()) {
|
||||
if (j->is_stopped() && j->get_flag(job_flag_t::JOB_CONTROL) && (!j->is_completed())) {
|
||||
job = j.get();
|
||||
break;
|
||||
|
|
|
@ -61,7 +61,7 @@ int builtin_disown(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
|||
// Foreground jobs can be disowned.
|
||||
// Even jobs that aren't under job control can be disowned!
|
||||
job_t *job = nullptr;
|
||||
for (const auto &j : jobs()) {
|
||||
for (const auto &j : parser.jobs()) {
|
||||
if (j->is_constructed() && (!j->is_completed())) {
|
||||
job = j.get();
|
||||
break;
|
||||
|
|
|
@ -38,7 +38,7 @@ int builtin_fg(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
|||
// Select last constructed job (i.e. first job in the job queue) that can be brought
|
||||
// to the foreground.
|
||||
|
||||
for (const auto &j : jobs()) {
|
||||
for (const auto &j : parser.jobs()) {
|
||||
if (j->is_constructed() && (!j->is_completed()) &&
|
||||
((j->is_stopped() || (!j->is_foreground())) &&
|
||||
j->get_flag(job_flag_t::JOB_CONTROL))) {
|
||||
|
@ -103,9 +103,9 @@ int builtin_fg(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
|||
if (!ft.empty()) parser.vars().set_one(L"_", ENV_EXPORT, ft);
|
||||
reader_write_title(job->command(), parser);
|
||||
|
||||
job->promote();
|
||||
parser.job_promote(job);
|
||||
job->set_flag(job_flag_t::FOREGROUND, true);
|
||||
|
||||
job->continue_job(true, job->is_stopped());
|
||||
job->continue_job(parser, true, job->is_stopped());
|
||||
return STATUS_CMD_OK;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "common.h"
|
||||
#include "fallback.h" // IWYU pragma: keep
|
||||
#include "io.h"
|
||||
#include "parser.h"
|
||||
#include "proc.h"
|
||||
#include "wgetopt.h"
|
||||
#include "wutil.h" // IWYU pragma: keep
|
||||
|
@ -170,7 +171,7 @@ int builtin_jobs(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
|||
|
||||
if (print_last) {
|
||||
// Ignore unconstructed jobs, i.e. ourself.
|
||||
for (const auto &j : jobs()) {
|
||||
for (const auto &j : parser.jobs()) {
|
||||
if (j->is_visible()) {
|
||||
builtin_jobs_print(j.get(), mode, !streams.out_is_redirected, streams);
|
||||
return STATUS_CMD_ERROR;
|
||||
|
@ -212,7 +213,7 @@ int builtin_jobs(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
for (const auto &j : jobs()) {
|
||||
for (const auto &j : parser.jobs()) {
|
||||
// Ignore unconstructed jobs, i.e. ourself.
|
||||
if (j->is_visible()) {
|
||||
builtin_jobs_print(j.get(), mode, !found && !streams.out_is_redirected,
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "builtin.h"
|
||||
#include "builtin_wait.h"
|
||||
#include "common.h"
|
||||
#include "parser.h"
|
||||
#include "proc.h"
|
||||
#include "reader.h"
|
||||
#include "wgetopt.h"
|
||||
|
@ -15,8 +16,8 @@
|
|||
/// Return the job id to which the process with pid belongs.
|
||||
/// If a specified process has already finished but the job hasn't, parser_t::job_get_from_pid()
|
||||
/// doesn't work properly, so use this function in wait command.
|
||||
static job_id_t get_job_id_from_pid(pid_t pid) {
|
||||
for (const auto &j : jobs()) {
|
||||
static job_id_t get_job_id_from_pid(pid_t pid, const parser_t &parser) {
|
||||
for (const auto &j : parser.jobs()) {
|
||||
if (j->pgid == pid) {
|
||||
return j->job_id;
|
||||
}
|
||||
|
@ -30,8 +31,8 @@ static job_id_t get_job_id_from_pid(pid_t pid) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool all_jobs_finished() {
|
||||
for (const auto &j : jobs()) {
|
||||
static bool all_jobs_finished(const parser_t &parser) {
|
||||
for (const auto &j : parser.jobs()) {
|
||||
// If any job is not completed, return false.
|
||||
// If there are stopped jobs, they are ignored.
|
||||
if (j->is_constructed() && !j->is_completed() && !j->is_stopped()) {
|
||||
|
@ -41,14 +42,14 @@ static bool all_jobs_finished() {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool any_jobs_finished(size_t jobs_len) {
|
||||
static bool any_jobs_finished(size_t jobs_len, const parser_t &parser) {
|
||||
bool no_jobs_running = true;
|
||||
|
||||
// If any job is removed from list, return true.
|
||||
if (jobs_len != jobs().size()) {
|
||||
if (jobs_len != parser.jobs().size()) {
|
||||
return true;
|
||||
}
|
||||
for (const auto &j : jobs()) {
|
||||
for (const auto &j : parser.jobs()) {
|
||||
// If any job is completed, return true.
|
||||
if (j->is_constructed() && (j->is_completed() || j->is_stopped())) {
|
||||
return true;
|
||||
|
@ -65,9 +66,10 @@ static bool any_jobs_finished(size_t jobs_len) {
|
|||
}
|
||||
|
||||
static int wait_for_backgrounds(parser_t &parser, bool any_flag) {
|
||||
size_t jobs_len = jobs().size();
|
||||
size_t jobs_len = parser.jobs().size();
|
||||
|
||||
while ((!any_flag && !all_jobs_finished()) || (any_flag && !any_jobs_finished(jobs_len))) {
|
||||
while ((!any_flag && !all_jobs_finished(parser)) ||
|
||||
(any_flag && !any_jobs_finished(jobs_len, parser))) {
|
||||
if (reader_test_interrupted()) {
|
||||
return 128 + SIGINT;
|
||||
}
|
||||
|
@ -137,10 +139,11 @@ static bool match_pid(const wcstring &cmd, const wchar_t *proc) {
|
|||
}
|
||||
|
||||
/// It should search the job list for something matching the given proc.
|
||||
static bool find_job_by_name(const wchar_t *proc, std::vector<job_id_t> &ids) {
|
||||
static bool find_job_by_name(const wchar_t *proc, std::vector<job_id_t> &ids,
|
||||
const parser_t &parser) {
|
||||
bool found = false;
|
||||
|
||||
for (const auto &j : jobs()) {
|
||||
for (const auto &j : parser.jobs()) {
|
||||
if (j->command_is_empty()) continue;
|
||||
|
||||
if (match_pid(j->command(), proc)) {
|
||||
|
@ -219,7 +222,7 @@ int builtin_wait(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
|||
argv[i]);
|
||||
continue;
|
||||
}
|
||||
if (job_id_t id = get_job_id_from_pid(pid)) {
|
||||
if (job_id_t id = get_job_id_from_pid(pid, parser)) {
|
||||
waited_job_ids.push_back(id);
|
||||
} else {
|
||||
streams.err.append_format(
|
||||
|
@ -227,7 +230,7 @@ int builtin_wait(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
|||
}
|
||||
} else {
|
||||
// argument is process name
|
||||
if (!find_job_by_name(argv[i], waited_job_ids)) {
|
||||
if (!find_job_by_name(argv[i], waited_job_ids, parser)) {
|
||||
streams.err.append_format(
|
||||
_(L"%ls: Could not find child processes with the name '%ls'\n"), cmd,
|
||||
argv[i]);
|
||||
|
|
|
@ -1120,7 +1120,7 @@ bool exec_job(parser_t &parser, shared_ptr<job_t> j) {
|
|||
return false;
|
||||
}
|
||||
|
||||
j->continue_job(reclaim_foreground_pgrp, false);
|
||||
j->continue_job(parser, reclaim_foreground_pgrp, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -491,7 +491,6 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
history_save_all();
|
||||
proc_destroy();
|
||||
if (opts.print_rusage_self) {
|
||||
print_rusage_self(stderr);
|
||||
}
|
||||
|
|
|
@ -5327,8 +5327,6 @@ int main(int argc, char **argv) {
|
|||
say(L"Encountered %d errors in low-level tests", err_count);
|
||||
if (s_test_run_count == 0) say(L"*** No Tests Were Actually Run! ***");
|
||||
|
||||
proc_destroy();
|
||||
|
||||
if (err_count != 0) {
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -797,7 +797,7 @@ parse_execution_result_t parse_execution_context_t::populate_plain_process(
|
|||
// Protect against exec with background processes running
|
||||
if (process_type == process_type_t::exec && shell_is_interactive()) {
|
||||
bool have_bg = false;
|
||||
for (const auto &bg : jobs()) {
|
||||
for (const auto &bg : parser->jobs()) {
|
||||
// The assumption here is that if it is a foreground job,
|
||||
// it's related to us.
|
||||
// This stops us from asking if we're doing `exec` inside a function.
|
||||
|
@ -811,11 +811,11 @@ parse_execution_result_t parse_execution_context_t::populate_plain_process(
|
|||
uint64_t current_run_count = reader_run_count();
|
||||
uint64_t &last_exec_run_count = parser->libdata().last_exec_run_counter;
|
||||
if (isatty(STDIN_FILENO) && current_run_count - 1 != last_exec_run_count) {
|
||||
reader_bg_job_warning();
|
||||
reader_bg_job_warning(*parser);
|
||||
last_exec_run_count = current_run_count;
|
||||
return parse_execution_errored;
|
||||
} else {
|
||||
hup_background_jobs();
|
||||
hup_background_jobs(*parser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1142,10 +1142,10 @@ parse_execution_result_t parse_execution_context_t::populate_job_from_job_node(
|
|||
return result;
|
||||
}
|
||||
|
||||
static bool remove_job(job_t *job) {
|
||||
for (auto j = jobs().begin(); j != jobs().end(); ++j) {
|
||||
static bool remove_job(parser_t &parser, job_t *job) {
|
||||
for (auto j = parser.jobs().begin(); j != parser.jobs().end(); ++j) {
|
||||
if (j->get() == job) {
|
||||
jobs().erase(j);
|
||||
parser.jobs().erase(j);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1276,7 +1276,7 @@ parse_execution_result_t parse_execution_context_t::run_1_job(tnode_t<g::job> jo
|
|||
|
||||
// Actually execute the job.
|
||||
if (!exec_job(*this->parser, job)) {
|
||||
remove_job(job.get());
|
||||
remove_job(*this->parser, job.get());
|
||||
}
|
||||
|
||||
// Update universal vaiables on external conmmands.
|
||||
|
|
|
@ -571,24 +571,24 @@ wcstring parser_t::current_line() {
|
|||
void parser_t::job_add(shared_ptr<job_t> job) {
|
||||
assert(job != NULL);
|
||||
assert(!job->processes.empty());
|
||||
this->my_job_list.push_front(std::move(job));
|
||||
job_list.push_front(std::move(job));
|
||||
}
|
||||
|
||||
void parser_t::job_promote(job_t *job) {
|
||||
job_list_t::iterator loc;
|
||||
for (loc = my_job_list.begin(); loc != my_job_list.end(); ++loc) {
|
||||
for (loc = job_list.begin(); loc != job_list.end(); ++loc) {
|
||||
if (loc->get() == job) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(loc != my_job_list.end());
|
||||
assert(loc != job_list.end());
|
||||
|
||||
// Move the job to the beginning.
|
||||
std::rotate(my_job_list.begin(), loc, my_job_list.end());
|
||||
std::rotate(job_list.begin(), loc, job_list.end());
|
||||
}
|
||||
|
||||
job_t *parser_t::job_get(job_id_t id) {
|
||||
for (const auto &job : my_job_list) {
|
||||
for (const auto &job : job_list) {
|
||||
if (id <= 0 || job->job_id == id) return job.get();
|
||||
}
|
||||
return NULL;
|
||||
|
|
|
@ -172,7 +172,7 @@ class parser_t : public std::enable_shared_from_this<parser_t> {
|
|||
/// List of called functions, used to help prevent infinite recursion.
|
||||
wcstring_list_t forbidden_function;
|
||||
/// The jobs associated with this parser.
|
||||
job_list_t my_job_list;
|
||||
job_list_t job_list;
|
||||
/// The list of blocks
|
||||
std::vector<std::unique_ptr<block_t>> block_stack;
|
||||
/// The 'depth' of the fish call stack.
|
||||
|
@ -274,7 +274,8 @@ class parser_t : public std::enable_shared_from_this<parser_t> {
|
|||
size_t block_count() const { return block_stack.size(); }
|
||||
|
||||
/// Get the list of jobs.
|
||||
job_list_t &job_list() { return my_job_list; }
|
||||
job_list_t &jobs() { return job_list; }
|
||||
const job_list_t &jobs() const { return job_list; }
|
||||
|
||||
/// Get the variables.
|
||||
env_stack_t &vars() { return variables; }
|
||||
|
|
60
src/proc.cpp
60
src/proc.cpp
|
@ -55,16 +55,6 @@ static owning_lock<statuses_t> last_statuses{statuses_t::just(0)};
|
|||
/// The signals that signify crashes to us.
|
||||
static const int crashsignals[] = {SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGSYS};
|
||||
|
||||
bool job_list_is_empty() {
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
return parser_t::principal_parser().job_list().empty();
|
||||
}
|
||||
|
||||
job_list_t &jobs() {
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
return parser_t::principal_parser().job_list();
|
||||
}
|
||||
|
||||
bool is_interactive_session = false;
|
||||
bool is_subshell = false;
|
||||
bool is_block = false;
|
||||
|
@ -96,18 +86,6 @@ static std::vector<int> interactive_stack;
|
|||
|
||||
void proc_init() { proc_push_interactive(0); }
|
||||
|
||||
void job_t::promote() {
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
parser_t::principal_parser().job_promote(this);
|
||||
}
|
||||
|
||||
void proc_destroy() {
|
||||
for (const auto &job : jobs()) {
|
||||
debug(2, L"freeing leaked job %ls", job->command_wcstr());
|
||||
}
|
||||
jobs().clear();
|
||||
}
|
||||
|
||||
void proc_set_last_statuses(statuses_t s) {
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
*last_statuses.acquire() = std::move(s);
|
||||
|
@ -332,7 +310,7 @@ void add_disowned_pgid(pid_t pgid) {
|
|||
/// See if any reapable processes have exited, and mark them accordingly.
|
||||
/// \param block_ok if no reapable processes have exited, block until one is (or until we receive a
|
||||
/// signal).
|
||||
static void process_mark_finished_children(bool block_ok) {
|
||||
static void process_mark_finished_children(parser_t &parser, bool block_ok) {
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
|
||||
// Get the exit and signal generations of all reapable processes.
|
||||
|
@ -342,7 +320,7 @@ static void process_mark_finished_children(bool block_ok) {
|
|||
topic_set_t reaptopics{};
|
||||
generation_list_t gens{};
|
||||
gens.fill(invalid_generation);
|
||||
for (const auto j : jobs()) {
|
||||
for (const auto &j : parser.jobs()) {
|
||||
for (const auto &proc : j->processes) {
|
||||
if (auto mtopic = j->reap_topic_for_process(proc.get())) {
|
||||
topic_t topic = *mtopic;
|
||||
|
@ -367,7 +345,7 @@ static void process_mark_finished_children(bool block_ok) {
|
|||
|
||||
// We got some changes. Since we last checked we received SIGCHLD, and or HUP/INT.
|
||||
// Update the hup/int generations and reap any reapable processes.
|
||||
for (const auto &j : jobs()) {
|
||||
for (const auto &j : parser.jobs()) {
|
||||
for (const auto &proc : j->processes) {
|
||||
if (auto mtopic = j->reap_topic_for_process(proc.get())) {
|
||||
// Update the signal hup/int gen.
|
||||
|
@ -575,15 +553,15 @@ static bool process_clean_after_marking(parser_t &parser, bool allow_interactive
|
|||
const bool interactive = allow_interactive && cur_term != NULL;
|
||||
|
||||
// Remove all disowned jobs.
|
||||
remove_disowned_jobs(jobs());
|
||||
remove_disowned_jobs(parser.jobs());
|
||||
|
||||
// Accumulate exit events into a new list, which we fire after the list manipulation is
|
||||
// complete.
|
||||
std::vector<event_t> exit_events;
|
||||
|
||||
// Print status messages for completed or stopped jobs.
|
||||
const bool only_one_job = jobs().size() == 1;
|
||||
for (const auto &j : jobs()) {
|
||||
const bool only_one_job = parser.jobs().size() == 1;
|
||||
for (const auto &j : parser.jobs()) {
|
||||
// Skip unconstructed jobs.
|
||||
if (!j->is_constructed()) {
|
||||
continue;
|
||||
|
@ -625,7 +603,8 @@ static bool process_clean_after_marking(parser_t &parser, bool allow_interactive
|
|||
// Do this before calling out to user code in the event handler below, to ensure an event
|
||||
// handler doesn't remove jobs on our behalf.
|
||||
auto is_complete = [](const shared_ptr<job_t> &j) { return j->is_completed(); };
|
||||
jobs().erase(std::remove_if(jobs().begin(), jobs().end(), is_complete), jobs().end());
|
||||
auto &jobs = parser.jobs();
|
||||
jobs.erase(std::remove_if(jobs.begin(), jobs.end(), is_complete), jobs.end());
|
||||
|
||||
// Post pending exit events.
|
||||
for (const auto &evt : exit_events) {
|
||||
|
@ -641,7 +620,7 @@ static bool process_clean_after_marking(parser_t &parser, bool allow_interactive
|
|||
|
||||
bool job_reap(parser_t &parser, bool allow_interactive) {
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
process_mark_finished_children(false);
|
||||
process_mark_finished_children(parser, false);
|
||||
|
||||
// Preserve the exit status.
|
||||
auto saved_statuses = proc_get_last_statuses();
|
||||
|
@ -693,8 +672,8 @@ unsigned long proc_get_jiffies(process_t *p) {
|
|||
}
|
||||
|
||||
/// Update the CPU time for all jobs.
|
||||
void proc_update_jiffies() {
|
||||
for (const auto &job : jobs()) {
|
||||
void proc_update_jiffies(parser_t &parser) {
|
||||
for (const auto &job : parser.jobs()) {
|
||||
for (process_ptr_t &p : job->processes) {
|
||||
gettimeofday(&p->last_time, 0);
|
||||
p->last_jiffies = proc_get_jiffies(p.get());
|
||||
|
@ -858,9 +837,9 @@ return false;
|
|||
return true;
|
||||
}
|
||||
|
||||
void job_t::continue_job(bool reclaim_foreground_pgrp, bool send_sigcont) {
|
||||
void job_t::continue_job(parser_t &parser, bool reclaim_foreground_pgrp, bool send_sigcont) {
|
||||
// Put job first in the job list.
|
||||
promote();
|
||||
parser.job_promote(this);
|
||||
set_flag(job_flag_t::NOTIFIED, false);
|
||||
|
||||
debug(4, L"%ls job %d, gid %d (%ls), %ls, %ls", send_sigcont ? L"Continue" : L"Start", job_id,
|
||||
|
@ -909,7 +888,7 @@ void job_t::continue_job(bool reclaim_foreground_pgrp, bool send_sigcont) {
|
|||
if (is_foreground()) {
|
||||
// Wait for the status of our own job to change.
|
||||
while (!reader_exit_forced() && !is_stopped() && !is_completed()) {
|
||||
process_mark_finished_children(true);
|
||||
process_mark_finished_children(parser, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -924,10 +903,10 @@ void job_t::continue_job(bool reclaim_foreground_pgrp, bool send_sigcont) {
|
|||
}
|
||||
}
|
||||
|
||||
void proc_sanity_check() {
|
||||
void proc_sanity_check(const parser_t &parser) {
|
||||
const job_t *fg_job = NULL;
|
||||
|
||||
for (const auto &j : jobs()) {
|
||||
for (const auto &j : parser.jobs()) {
|
||||
if (!j->is_constructed()) continue;
|
||||
|
||||
// More than one foreground job?
|
||||
|
@ -979,12 +958,13 @@ void proc_pop_interactive() {
|
|||
|
||||
void proc_wait_any(parser_t &parser) {
|
||||
ASSERT_IS_MAIN_THREAD();
|
||||
process_mark_finished_children(true /* block_ok */);
|
||||
process_mark_finished_children(parser, true /* block_ok */);
|
||||
process_clean_after_marking(parser, is_interactive);
|
||||
}
|
||||
|
||||
void hup_background_jobs() {
|
||||
for (const auto &j : jobs()) {
|
||||
void hup_background_jobs(const parser_t &parser) {
|
||||
// TODO: we should probably hup all jobs across all parsers here.
|
||||
for (const auto &j : parser.jobs()) {
|
||||
// Make sure we don't try to SIGHUP the calling builtin
|
||||
if (j->pgid == INVALID_PID || !j->get_flag(job_flag_t::JOB_CONTROL)) {
|
||||
continue;
|
||||
|
|
21
src/proc.h
21
src/proc.h
|
@ -153,6 +153,7 @@ class internal_proc_t {
|
|||
///
|
||||
/// If the process is of type process_type_t::function, argv is the argument vector, and argv[0] is
|
||||
/// the name of the shellscript function.
|
||||
class parser_t;
|
||||
class process_t {
|
||||
private:
|
||||
null_terminated_array_t<wchar_t> argv_array;
|
||||
|
@ -406,7 +407,6 @@ class job_t {
|
|||
/// \return whether this job and its parent chain are fully constructed.
|
||||
bool job_chain_is_fully_constructed() const;
|
||||
|
||||
// (This function would just be called `continue` but that's obviously a reserved keyword)
|
||||
/// Resume a (possibly) stopped job. Puts job in the foreground. If cont is true, restore the
|
||||
/// saved terminal modes and send the process group a SIGCONT signal to wake it up before we
|
||||
/// block.
|
||||
|
@ -414,10 +414,7 @@ class job_t {
|
|||
/// \param reclaim_foreground_pgrp whether, when the job finishes or stops, to reclaim the
|
||||
/// foreground pgrp (via tcsetpgrp). \param send_sigcont Whether SIGCONT should be sent to the
|
||||
/// job if it is in the foreground.
|
||||
void continue_job(bool reclaim_foreground_pgrp, bool send_sigcont);
|
||||
|
||||
/// Promotes the job to the front of the job list.
|
||||
void promote();
|
||||
void continue_job(parser_t &parser, bool reclaim_foreground_pgrp, bool send_sigcont);
|
||||
|
||||
/// Send the specified signal to all processes in this job.
|
||||
/// \return true on success, false on failure.
|
||||
|
@ -459,11 +456,6 @@ extern int is_event;
|
|||
// List of jobs.
|
||||
typedef std::deque<shared_ptr<job_t>> job_list_t;
|
||||
|
||||
bool job_list_is_empty(void);
|
||||
|
||||
/// A helper function to more easily access the job list
|
||||
job_list_t &jobs();
|
||||
|
||||
/// The current job control mode.
|
||||
///
|
||||
/// Must be one of job_control_t::all, job_control_t::interactive and job_control_t::none.
|
||||
|
@ -497,11 +489,11 @@ unsigned long proc_get_jiffies(process_t *p);
|
|||
|
||||
/// Update process time usage for all processes by calling the proc_get_jiffies function for every
|
||||
/// process of every job.
|
||||
void proc_update_jiffies();
|
||||
void proc_update_jiffies(parser_t &parser);
|
||||
|
||||
/// Perform a set of simple sanity checks on the job list. This includes making sure that only one
|
||||
/// job is in the foreground, that every process is in a valid state, etc.
|
||||
void proc_sanity_check();
|
||||
void proc_sanity_check(const parser_t &parser);
|
||||
|
||||
/// Create a process/job exit event notification.
|
||||
event_t proc_create_event(const wchar_t *msg, event_type_t type, pid_t pid, int status);
|
||||
|
@ -509,9 +501,6 @@ event_t proc_create_event(const wchar_t *msg, event_type_t type, pid_t pid, int
|
|||
/// Initializations.
|
||||
void proc_init();
|
||||
|
||||
/// Clean up before exiting.
|
||||
void proc_destroy();
|
||||
|
||||
/// Set new value for is_interactive flag, saving previous value. If needed, update signal handlers.
|
||||
void proc_push_interactive(int value);
|
||||
|
||||
|
@ -528,7 +517,7 @@ void set_is_within_fish_initialization(bool flag);
|
|||
bool is_within_fish_initialization();
|
||||
|
||||
/// Terminate all background jobs
|
||||
void hup_background_jobs();
|
||||
void hup_background_jobs(const parser_t &parser);
|
||||
|
||||
/// Give ownership of the terminal to the specified job.
|
||||
///
|
||||
|
|
|
@ -1972,7 +1972,7 @@ void reader_run_command(parser_t &parser, const wcstring &cmd) {
|
|||
parser.vars().set_one(L"_", ENV_GLOBAL, program_name);
|
||||
|
||||
if (have_proc_stat) {
|
||||
proc_update_jiffies();
|
||||
proc_update_jiffies(parser);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2190,11 +2190,11 @@ void reader_import_history_if_necessary() {
|
|||
|
||||
bool shell_is_exiting() { return should_exit(); }
|
||||
|
||||
void reader_bg_job_warning() {
|
||||
void reader_bg_job_warning(const parser_t &parser) {
|
||||
std::fputws(_(L"There are still jobs active:\n"), stdout);
|
||||
std::fputws(_(L"\n PID Command\n"), stdout);
|
||||
|
||||
for (const auto &j : jobs()) {
|
||||
for (const auto &j : parser.jobs()) {
|
||||
if (!j->is_completed()) {
|
||||
std::fwprintf(stdout, L"%6d %ls\n", j->processes[0]->pid, j->command_wcstr());
|
||||
}
|
||||
|
@ -2206,9 +2206,8 @@ void reader_bg_job_warning() {
|
|||
|
||||
/// 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() {
|
||||
static void handle_end_loop(const parser_t &parser) {
|
||||
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
|
||||
|
@ -2218,7 +2217,7 @@ static void handle_end_loop() {
|
|||
}
|
||||
|
||||
bool bg_jobs = false;
|
||||
for (const auto &j : jobs()) {
|
||||
for (const auto &j : parser.jobs()) {
|
||||
if (!j->is_completed()) {
|
||||
bg_jobs = true;
|
||||
break;
|
||||
|
@ -2227,7 +2226,7 @@ static void handle_end_loop() {
|
|||
|
||||
reader_data_t *data = current_data();
|
||||
if (!data->prev_end_loop && bg_jobs) {
|
||||
reader_bg_job_warning();
|
||||
reader_bg_job_warning(parser);
|
||||
reader_set_end_loop(false);
|
||||
data->prev_end_loop = 1;
|
||||
return;
|
||||
|
@ -2235,7 +2234,7 @@ static void handle_end_loop() {
|
|||
}
|
||||
|
||||
// Kill remaining jobs before exiting.
|
||||
hup_background_jobs();
|
||||
hup_background_jobs(parser);
|
||||
}
|
||||
|
||||
static bool selection_is_at_top() {
|
||||
|
@ -2269,7 +2268,7 @@ static int read_i() {
|
|||
reader_data_t *data = current_data();
|
||||
data->prev_end_loop = 0;
|
||||
|
||||
while (!shell_is_exiting() && (!sanity_check())) {
|
||||
while (!shell_is_exiting()) {
|
||||
event_fire_generic(L"fish_prompt");
|
||||
run_count++;
|
||||
|
||||
|
@ -2292,7 +2291,7 @@ static int read_i() {
|
|||
maybe_t<wcstring> tmp = reader_readline(0);
|
||||
|
||||
if (shell_is_exiting()) {
|
||||
handle_end_loop();
|
||||
handle_end_loop(parser);
|
||||
} else if (tmp) {
|
||||
const wcstring command = tmp.acquire();
|
||||
data->update_buff_pos(&data->command_line, 0);
|
||||
|
@ -2307,7 +2306,7 @@ static int read_i() {
|
|||
data->history->resolve_pending();
|
||||
}
|
||||
if (shell_is_exiting()) {
|
||||
handle_end_loop();
|
||||
handle_end_loop(parser);
|
||||
} else {
|
||||
data->prev_end_loop = 0;
|
||||
}
|
||||
|
|
|
@ -232,7 +232,7 @@ wcstring completion_apply_to_command_line(const wcstring &val_str, complete_flag
|
|||
bool append_only);
|
||||
|
||||
/// Print warning with list of backgrounded jobs
|
||||
void reader_bg_job_warning();
|
||||
void reader_bg_job_warning(const parser_t &parser);
|
||||
|
||||
/// Return the current interactive reads loop count. Useful for determining how many commands have
|
||||
/// been executed between invocations of code.
|
||||
|
|
|
@ -20,12 +20,6 @@ void sanity_lose() {
|
|||
insane = true;
|
||||
}
|
||||
|
||||
bool sanity_check() {
|
||||
if (!insane) reader_sanity_check();
|
||||
if (!insane) proc_sanity_check();
|
||||
return insane;
|
||||
}
|
||||
|
||||
void validate_pointer(const void *ptr, const wchar_t *err, int null_ok) {
|
||||
// Test if the pointer data crosses a segment boundary.
|
||||
if ((0x00000003l & (intptr_t)ptr) != 0) {
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
/// Call this function to tell the program it is not in a sane state.
|
||||
void sanity_lose();
|
||||
|
||||
/// Perform sanity checks, return 1 if program is in a sane state 0 otherwise.
|
||||
bool sanity_check();
|
||||
|
||||
/// Try and determine if ptr is a valid pointer. If not, loose sanity.
|
||||
///
|
||||
/// \param ptr The pointer to validate
|
||||
|
|
Loading…
Reference in a new issue