diff --git a/src/builtin_eval.cpp b/src/builtin_eval.cpp index b80fc3357..e8da6c7c8 100644 --- a/src/builtin_eval.cpp +++ b/src/builtin_eval.cpp @@ -59,7 +59,7 @@ int builtin_eval(parser_t &parser, io_streams_t &streams, wchar_t **argv) { } int status = STATUS_CMD_OK; - auto res = parser.eval(new_cmd, ios, streams.job_tree); + auto res = parser.eval(new_cmd, ios, streams.job_group); if (res.was_empty) { // Issue #5692, in particular, to catch `eval ""`, `eval "begin; end;"`, etc. // where we have an argument but nothing is executed. diff --git a/src/exec.cpp b/src/exec.cpp index 0faa5e1e5..041eb654b 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -175,7 +175,7 @@ static void internal_exec(env_stack_t &vars, job_t *j, const io_chain_t &block_i /// If our pgroup assignment mode wants us to use the first external proc, then apply it here. /// \returns the job's pgid, which should always be set to something valid after this call. static pid_t maybe_assign_pgid_from_child(const std::shared_ptr &j, pid_t child_pid) { - auto &jt = j->job_tree; + auto &jt = j->group; if (jt->needs_pgid_assignment()) { jt->set_pgid(child_pid); } @@ -309,8 +309,7 @@ bool blocked_signals_for_job(const job_t &job, sigset_t *sigmask) { static bool fork_child_for_process(const std::shared_ptr &job, process_t *p, const dup2_list_t &dup2s, const char *fork_type, const std::function &child_action) { - assert(!job->job_tree->is_placeholder() && - "Placeholders are for internal functions, they should never fork"); + assert(!job->group->is_internal() && "Internal groups should never need to fork"); pid_t pid = execute_fork(); if (pid == 0) { // This is the child process. Setup redirections, print correct output to @@ -637,15 +636,15 @@ static proc_performer_t get_performer_for_process(process_t *p, job_t *job, const io_chain_t &io_chain) { assert((p->type == process_type_t::function || p->type == process_type_t::block_node) && "Unexpected process type"); - // We want to capture the job tree. - job_tree_ref_t job_tree = job->job_tree; + // We want to capture the job group. + job_group_ref_t job_group = job->group; if (p->type == process_type_t::block_node) { const parsed_source_ref_t &source = p->block_node_source; tnode_t node = p->internal_block_node; assert(source && node && "Process is missing node info"); return [=](parser_t &parser) { - return parser.eval_node(source, node, io_chain, job_tree).status; + return parser.eval_node(source, node, io_chain, job_group).status; }; } else { assert(p->type == process_type_t::function); @@ -659,7 +658,7 @@ static proc_performer_t get_performer_for_process(process_t *p, job_t *job, // Pull out the job list from the function. tnode_t body = props->func_node.child<1>(); const block_t *fb = function_prepare_environment(parser, *argv, *props); - auto res = parser.eval_node(props->parsed_source, body, io_chain, job_tree); + auto res = parser.eval_node(props->parsed_source, body, io_chain, job_group); function_restore_environment(parser, fb); // If the function did not execute anything, treat it as success. @@ -832,7 +831,7 @@ static bool exec_process_in_job(parser_t &parser, process_t *p, const std::share case process_type_t::builtin: { io_streams_t builtin_io_streams{stdout_read_limit}; - builtin_io_streams.job_tree = j->job_tree; + builtin_io_streams.job_group = j->group; if (!exec_internal_builtin_proc(parser, p, pipe_read.get(), process_net_io_chain, builtin_io_streams)) { return false; @@ -1066,14 +1065,14 @@ static void populate_subshell_output(wcstring_list_t *lst, const io_buffer_t &bu /// Execute \p cmd in a subshell in \p parser. If \p lst is not null, populate it with the output. /// Return $status in \p out_status. -/// If \p job_tree is set, any spawned commands should join that job tree. +/// If \p job_group is set, any spawned commands should join that job group. /// If \p apply_exit_status is false, then reset $status back to its original value. /// \p is_subcmd controls whether we apply a read limit. /// \p break_expand is used to propagate whether the result should be "expansion breaking" in the /// sense that subshells used during string expansion should halt that expansion. \return the value /// of $status. static int exec_subshell_internal(const wcstring &cmd, parser_t &parser, - const job_tree_ref_t &job_tree, wcstring_list_t *lst, + const job_group_ref_t &job_group, wcstring_list_t *lst, bool *break_expand, bool apply_exit_status, bool is_subcmd) { ASSERT_IS_MAIN_THREAD(); auto &ld = parser.libdata(); @@ -1097,7 +1096,7 @@ static int exec_subshell_internal(const wcstring &cmd, parser_t &parser, *break_expand = true; return STATUS_CMD_ERROR; } - eval_res_t eval_res = parser.eval(cmd, io_chain_t{bufferfill}, job_tree, block_type_t::subst); + eval_res_t eval_res = parser.eval(cmd, io_chain_t{bufferfill}, job_group, block_type_t::subst); std::shared_ptr buffer = io_bufferfill_t::finish(std::move(bufferfill)); if (buffer->buffer().discarded()) { *break_expand = true; @@ -1116,11 +1115,11 @@ static int exec_subshell_internal(const wcstring &cmd, parser_t &parser, return eval_res.status.status_value(); } -int exec_subshell_for_expand(const wcstring &cmd, parser_t &parser, const job_tree_ref_t &job_tree, - wcstring_list_t &outputs) { +int exec_subshell_for_expand(const wcstring &cmd, parser_t &parser, + const job_group_ref_t &job_group, wcstring_list_t &outputs) { ASSERT_IS_MAIN_THREAD(); bool break_expand = false; - int ret = exec_subshell_internal(cmd, parser, job_tree, &outputs, &break_expand, true, true); + int ret = exec_subshell_internal(cmd, parser, job_group, &outputs, &break_expand, true, true); // Only return an error code if we should break expansion. return break_expand ? ret : STATUS_CMD_OK; } diff --git a/src/exec.h b/src/exec.h index 5098e6580..426119645 100644 --- a/src/exec.h +++ b/src/exec.h @@ -31,8 +31,8 @@ int exec_subshell(const wcstring &cmd, parser_t &parser, wcstring_list_t &output /// "success" (even though the command may have failed), a non-zero return means that we should /// halt expansion. If the \p pgid is supplied, then any spawned external commands should join that /// pgroup. -int exec_subshell_for_expand(const wcstring &cmd, parser_t &parser, const job_tree_ref_t &job_tree, - wcstring_list_t &outputs); +int exec_subshell_for_expand(const wcstring &cmd, parser_t &parser, + const job_group_ref_t &job_group, wcstring_list_t &outputs); /// Loops over close until the syscall was run without being interrupted. void exec_close(int fd); diff --git a/src/expand.cpp b/src/expand.cpp index 2f5881487..2ef7a34f7 100644 --- a/src/expand.cpp +++ b/src/expand.cpp @@ -622,7 +622,7 @@ static expand_result_t expand_cmdsubst(wcstring input, const operation_context_t wcstring_list_t sub_res; const wcstring subcmd(paren_begin + 1, paren_end - paren_begin - 1); - int subshell_status = exec_subshell_for_expand(subcmd, *ctx.parser, ctx.job_tree, sub_res); + int subshell_status = exec_subshell_for_expand(subcmd, *ctx.parser, ctx.job_group, sub_res); if (subshell_status != 0) { // TODO: Ad-hoc switch, how can we enumerate the possible errors more safely? const wchar_t *err; diff --git a/src/io.h b/src/io.h index f5777ae7d..d2c039589 100644 --- a/src/io.h +++ b/src/io.h @@ -21,7 +21,7 @@ using std::shared_ptr; -class job_tree_t; +class job_group_t; /// A simple set of FDs. struct fd_set_t { @@ -464,10 +464,10 @@ struct io_streams_t { // Actual IO redirections. This is only used by the source builtin. Unowned. const io_chain_t *io_chain{nullptr}; - // The job tree of the job, if any. This enables builtins which run more code like eval() to + // The job group of the job, if any. This enables builtins which run more code like eval() to // share pgid. - // TODO: this is awkwardly placed. - std::shared_ptr job_tree{}; + // FIXME: this is awkwardly placed. + std::shared_ptr job_group{}; // io_streams_t cannot be copied. io_streams_t(const io_streams_t &) = delete; diff --git a/src/operation_context.h b/src/operation_context.h index f72f7e0aa..9e6ae73bc 100644 --- a/src/operation_context.h +++ b/src/operation_context.h @@ -7,7 +7,7 @@ class environment_t; class parser_t; -class job_tree_t; +class job_group_t; /// A common helper which always returns false. bool no_cancel(); @@ -30,10 +30,10 @@ class operation_context_t { // context itself. const environment_t &vars; - /// The job tree of the parental job. + /// The job group of the parental job. /// This is used only when expanding command substitutions. If this is set, any jobs created by /// the command substitions should use this tree. - std::shared_ptr job_tree{}; + std::shared_ptr job_group{}; // A function which may be used to poll for cancellation. cancel_checker_t cancel_checker; diff --git a/src/parse_execution.cpp b/src/parse_execution.cpp index 512aa2196..ef3b77f6b 100644 --- a/src/parse_execution.cpp +++ b/src/parse_execution.cpp @@ -1254,7 +1254,7 @@ end_execution_reason_t parse_execution_context_t::run_1_job(tnode_t job_ bool wants_job_control = (job_control_mode == job_control_t::all) || ((job_control_mode == job_control_t::interactive) && parser->is_interactive()) || - (ctx.job_tree && ctx.job_tree->wants_job_control()); + (ctx.job_group && ctx.job_group->wants_job_control()); job_t::properties_t props{}; props.wants_terminal = wants_job_control && !ld.is_event; @@ -1287,9 +1287,9 @@ end_execution_reason_t parse_execution_context_t::run_1_job(tnode_t job_ // Clean up the job on failure or cancellation. if (pop_result == end_execution_reason_t::ok) { - // Set the pgroup assignment mode and job tree, now that the job is populated. - job_tree_t::populate_tree_for_job(job.get(), ctx.job_tree); - assert(job->job_tree && "Should have a job tree"); + // Set the pgroup assignment mode and job group, now that the job is populated. + job_group_t::populate_tree_for_job(job.get(), ctx.job_group); + assert(job->group && "Should have a job group"); // Success. Give the job to the parser - it will clean it up. parser->job_add(job); diff --git a/src/parse_execution.h b/src/parse_execution.h index fa50712f8..8ac778a0f 100644 --- a/src/parse_execution.h +++ b/src/parse_execution.h @@ -145,7 +145,7 @@ class parse_execution_context_t { public: /// Construct a context in preparation for evaluating a node in a tree, with the given block_io. - /// The execution context may access the parser and job_tree through ctx. + /// The execution context may access the parser and group through ctx. parse_execution_context_t(parsed_source_ref_t pstree, const operation_context_t &ctx, io_chain_t block_io); diff --git a/src/parser.cpp b/src/parser.cpp index f62e76277..3fbc65200 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -632,12 +632,12 @@ profile_item_t *parser_t::create_profile_item() { return result; } -eval_res_t parser_t::eval(const wcstring &cmd, const io_chain_t &io, const job_tree_ref_t &job_tree, - enum block_type_t block_type) { +eval_res_t parser_t::eval(const wcstring &cmd, const io_chain_t &io, + const job_group_ref_t &job_group, enum block_type_t block_type) { // Parse the source into a tree, if we can. parse_error_list_t error_list; if (parsed_source_ref_t ps = parse_source(cmd, parse_flag_none, &error_list)) { - return this->eval(ps, io, job_tree, block_type); + return this->eval(ps, io, job_group, block_type); } else { // Get a backtrace. This includes the message. wcstring backtrace_and_desc; @@ -654,12 +654,12 @@ eval_res_t parser_t::eval(const wcstring &cmd, const io_chain_t &io, const job_t } eval_res_t parser_t::eval(const parsed_source_ref_t &ps, const io_chain_t &io, - const job_tree_ref_t &job_tree, enum block_type_t block_type) { + const job_group_ref_t &job_group, enum block_type_t block_type) { assert(block_type == block_type_t::top || block_type == block_type_t::subst); if (!ps->tree.empty()) { // Execute the first node. tnode_t start{&ps->tree, &ps->tree.front()}; - return this->eval_node(ps, start, io, job_tree, block_type); + return this->eval_node(ps, start, io, job_group, block_type); } else { auto status = proc_status_t::from_exit_code(get_last_status()); bool break_expand = false; @@ -670,7 +670,7 @@ eval_res_t parser_t::eval(const parsed_source_ref_t &ps, const io_chain_t &io, template eval_res_t parser_t::eval_node(const parsed_source_ref_t &ps, tnode_t node, - const io_chain_t &block_io, const job_tree_ref_t &job_tree, + const io_chain_t &block_io, const job_group_ref_t &job_group, block_type_t block_type) { static_assert( std::is_same::value || std::is_same::value, @@ -695,8 +695,8 @@ eval_res_t parser_t::eval_node(const parsed_source_ref_t &ps, tnode_t node, operation_context_t op_ctx = this->context(); block_t *scope_block = this->push_block(block_t::scope_block(block_type)); - // Propogate our job tree. - op_ctx.job_tree = job_tree; + // Propogate our job group. + op_ctx.job_group = job_group; // Create and set a new execution context. using exc_ctx_ref_t = std::unique_ptr; @@ -726,9 +726,9 @@ eval_res_t parser_t::eval_node(const parsed_source_ref_t &ps, tnode_t node, // Explicit instantiations. TODO: use overloads instead? template eval_res_t parser_t::eval_node(const parsed_source_ref_t &, tnode_t, - const io_chain_t &, const job_tree_ref_t &, block_type_t); + const io_chain_t &, const job_group_ref_t &, block_type_t); template eval_res_t parser_t::eval_node(const parsed_source_ref_t &, tnode_t, - const io_chain_t &, const job_tree_ref_t &, block_type_t); + const io_chain_t &, const job_group_ref_t &, block_type_t); void parser_t::get_backtrace(const wcstring &src, const parse_error_list_t &errors, wcstring &output) const { diff --git a/src/parser.h b/src/parser.h index 772d0369e..be8b001aa 100644 --- a/src/parser.h +++ b/src/parser.h @@ -282,27 +282,28 @@ class parser_t : public std::enable_shared_from_this { /// /// \param cmd the string to evaluate /// \param io io redirections to perform on all started jobs - /// \param job_tree if set, the job tree to give to spawned jobs. + /// \param job_group if set, the job group to give to spawned jobs. /// \param block_type The type of block to push on the block stack, which must be either 'top' /// or 'subst'. /// \param break_expand If not null, return by reference whether the error ought to be an expand /// error. This includes nested expand errors, and command-not-found. /// /// \return the result of evaluation. - eval_res_t eval(const wcstring &cmd, const io_chain_t &io, const job_tree_ref_t &job_tree = {}, + eval_res_t eval(const wcstring &cmd, const io_chain_t &io, + const job_group_ref_t &job_group = {}, block_type_t block_type = block_type_t::top); /// Evaluate the parsed source ps. /// Because the source has been parsed, a syntax error is impossible. eval_res_t eval(const parsed_source_ref_t &ps, const io_chain_t &io, - const job_tree_ref_t &job_tree = {}, + const job_group_ref_t &job_group = {}, block_type_t block_type = block_type_t::top); /// Evaluates a node. /// The node type must be grammar::statement or grammar::job_list. template eval_res_t eval_node(const parsed_source_ref_t &ps, tnode_t node, const io_chain_t &block_io, - const job_tree_ref_t &job_tree, + const job_group_ref_t &job_group, block_type_t block_type = block_type_t::top); /// Evaluate line as a list of parameters, i.e. tokenize it and perform parameter expansion and diff --git a/src/postfork.cpp b/src/postfork.cpp index caec20aea..634524a57 100644 --- a/src/postfork.cpp +++ b/src/postfork.cpp @@ -205,11 +205,11 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, // desired_pgid tracks the pgroup for the process. If it is none, the pgroup is left unchanged. // If it is zero, create a new pgroup from the pid. If it is >0, join that pgroup. maybe_t desired_pgid = none(); - if (auto job_pgid = j->job_tree->get_pgid()) { + if (auto job_pgid = j->group->get_pgid()) { desired_pgid = *job_pgid; } else { - assert(j->job_tree->needs_pgid_assignment() && "We should be expecting a pgid"); - // We are the first external proc in the job tree. Set the desired_pgid to 0 to indicate we + assert(j->group->needs_pgid_assignment() && "We should be expecting a pgid"); + // We are the first external proc in the job group. Set the desired_pgid to 0 to indicate we // should creating a new process group. desired_pgid = 0; } diff --git a/src/proc.cpp b/src/proc.cpp index ee1528c96..19414bde8 100644 --- a/src/proc.cpp +++ b/src/proc.cpp @@ -164,7 +164,7 @@ bool job_t::should_report_process_exits() const { return false; } -bool job_t::job_chain_is_fully_constructed() const { return job_tree->is_root_constructed(); } +bool job_t::job_chain_is_fully_constructed() const { return group->is_root_constructed(); } bool job_t::signal(int signal) { // Presumably we are distinguishing between the two cases below because we do @@ -241,38 +241,38 @@ void print_exit_warning_for_jobs(const job_list_t &jobs) { fputws(_(L"Use 'disown PID' to remove jobs from the list without terminating them.\n"), stdout); } -job_tree_t::job_tree_t(bool job_control, bool placeholder) +job_group_t::job_group_t(bool job_control, bool internal) : job_control_(job_control), - is_placeholder_(placeholder), - job_id_(placeholder ? -1 : acquire_job_id()) {} + is_internal_(internal), + job_id_(internal ? -1 : acquire_job_id()) {} -job_tree_t::~job_tree_t() { +job_group_t::~job_group_t() { if (job_id_ > 0) { release_job_id(job_id_); } } -void job_tree_t::set_pgid(pid_t pgid) { - // Note we need not be concerned about thread safety. job_trees are intended to be shared across - // threads, but their pgid should always have been set beforehand. +void job_group_t::set_pgid(pid_t pgid) { + // Note we need not be concerned about thread safety. job_groups are intended to be shared + // across threads, but their pgid should always have been set beforehand. assert(needs_pgid_assignment() && "We should not be setting a pgid"); assert(pgid >= 0 && "Invalid pgid"); pgid_ = pgid; } -maybe_t job_tree_t::get_pgid() const { return pgid_; } +maybe_t job_group_t::get_pgid() const { return pgid_; } -void job_tree_t::populate_tree_for_job(job_t *job, const job_tree_ref_t &proposed) { +void job_group_t::populate_tree_for_job(job_t *job, const job_group_ref_t &proposed) { // Note there's three cases to consider: - // nullptr -> this is a root job, there is no inherited job tree - // placeholder -> the parent is running as part of a simple function execution - // We may need to create a new job tree if we are going to fork. - // non-placeholder -> we are running as part of a real pipeline - // Decide if this job can use the placeholder tree. + // nullptr -> this is a root job, there is no inherited job group + // internal -> the parent is running as part of a simple function execution + // We may need to create a new job group if we are going to fork. + // non-internal -> we are running as part of a real pipeline + // Decide if this job can use an internal tree. // This is true if it's a simple foreground execution of an internal proc. bool first_proc_internal = job->processes.front()->is_internal(); - bool can_use_placeholder = !job->is_initially_background() && job->processes.size() == 1 && - job->processes.front()->is_internal(); + bool can_use_internal = !job->is_initially_background() && job->processes.size() == 1 && + job->processes.front()->is_internal(); bool needs_new_tree = false; if (!proposed) { @@ -281,8 +281,8 @@ void job_tree_t::populate_tree_for_job(job_t *job, const job_tree_ref_t &propose } else if (!job->is_foreground()) { // Background jobs always get a new tree. needs_new_tree = true; - } else if (proposed->is_placeholder() && !can_use_placeholder) { - // We cannot use the placeholder tree for this job. + } else if (proposed->is_internal() && !can_use_internal) { + // We cannot use the internal tree for this job. needs_new_tree = true; } @@ -290,18 +290,18 @@ void job_tree_t::populate_tree_for_job(job_t *job, const job_tree_ref_t &propose bool job_control = job->wants_job_control(); if (!needs_new_tree) { - job->job_tree = proposed; - } else if (can_use_placeholder) { - job->job_tree.reset(new job_tree_t(job_control, true)); + job->group = proposed; + } else if (can_use_internal) { + job->group.reset(new job_group_t(job_control, true)); } else { - job->job_tree.reset(new job_tree_t(job_control, false)); + job->group.reset(new job_group_t(job_control, false)); // Perhaps this job should immediately live in fish's pgroup. // There's two reasons why it may be so: // 1. The job doesn't need job control. // 2. The first process in the job is internal to fish; this needs to own the tty. if (!job_control || first_proc_internal) { - job->job_tree->set_pgid(getpgrp()); + job->group->set_pgid(getpgrp()); } } } @@ -390,7 +390,7 @@ void job_t::mark_constructed() { assert(!is_constructed() && "Job was already constructed"); mut_flags().constructed = true; if (flags().is_tree_root) { - job_tree->mark_root_constructed(); + group->mark_root_constructed(); } } diff --git a/src/proc.h b/src/proc.h index 8f8c3b0ae..eaae95e1c 100644 --- a/src/proc.h +++ b/src/proc.h @@ -160,26 +160,25 @@ using job_id_t = int; job_id_t acquire_job_id(void); void release_job_id(job_id_t jid); -/// job_tree_t is conceptually similar to the idea of a process group. It represents data which +/// job_group_t is conceptually similar to the idea of a process group. It represents data which /// is shared among all of the "subjobs" that may be spawned by a single job. /// For example, two fish functions in a pipeline may themselves spawn multiple jobs, but all will -/// share the same job tree. -/// There is also a notion of a "placeholder" job tree. Placeholders are used when executing a -/// foreground function or block. These are not jobs as the user understands them - they do not -/// consume a job ID, they do not show up in job lists, and they do not have a pgid because they -/// contain no external procs. -/// Note that job_tree_t is intended to eventually be shared between threads, and so must be thread -/// safe. +/// share the same job group. +/// There is also a notion of a "internal" job group. Internal groups are used when executing a +/// foreground function or block with no pipeline. These are not jobs as the user understands them - +/// they do not consume a job ID, they do not show up in job lists, and they do not have a pgid +/// because they contain no external procs. Note that job_group_t is intended to eventually be +/// shared between threads, and so must be thread safe. class job_t; -class job_tree_t; -using job_tree_ref_t = std::shared_ptr; +class job_group_t; +using job_group_ref_t = std::shared_ptr; -class job_tree_t { +class job_group_t { public: - /// Set the pgid for this job tree, latching it to this value. + /// Set the pgid for this job group, latching it to this value. /// The pgid should not already have been set. /// Of course this does not keep the pgid alive by itself. - /// The placeholder job tree does not have a pgid and it is an error to set it. + /// An internal job group does not have a pgid and it is an error to set it. void set_pgid(pid_t pgid); /// Get the pgid, or none() if it has not been set. @@ -188,12 +187,12 @@ class job_tree_t { /// \return whether we want job control bool wants_job_control() const { return job_control_; } - /// \return whether this is a placeholder. - bool is_placeholder() const { return is_placeholder_; } + /// \return whether this is an internal group. + bool is_internal() const { return is_internal_; } - /// \return whether this job tree is awaiting a pgid. - /// This is true for non-placeholder trees that don't already have a pgid. - bool needs_pgid_assignment() const { return !is_placeholder_ && !pgid_.has_value(); } + /// \return whether this job group is awaiting a pgid. + /// This is true for non-internal trees that don't already have a pgid. + bool needs_pgid_assignment() const { return !is_internal_ && !pgid_.has_value(); } /// \return the job ID, or -1 if none. job_id_t get_id() const { return job_id_; } @@ -204,20 +203,20 @@ class job_tree_t { void mark_root_constructed() { root_constructed_ = true; }; bool is_root_constructed() const { return root_constructed_; } - /// Given a job and a proposed job tree (possibly null), populate the job's tree. + /// Given a job and a proposed job group (possibly null), populate the job's tree. /// The proposed tree is the tree from the parent job, or null if this is a root. - static void populate_tree_for_job(job_t *job, const job_tree_ref_t &proposed_tree); + static void populate_tree_for_job(job_t *job, const job_group_ref_t &proposed_tree); - ~job_tree_t(); + ~job_group_t(); private: maybe_t pgid_{}; const bool job_control_; - const bool is_placeholder_; + const bool is_internal_; const job_id_t job_id_; relaxed_atomic_bool_t root_constructed_{}; - explicit job_tree_t(bool job_control, bool placeholder); + explicit job_group_t(bool job_control, bool internal); }; /// A structure representing a single fish process. Contains variables for tracking process state @@ -347,7 +346,6 @@ using job_id_t = int; job_id_t acquire_job_id(void); void release_job_id(job_id_t jid); - /// A struct representing a job. A job is a pipeline of one or more processes. class job_t { public: @@ -439,22 +437,22 @@ class job_t { /// All the processes in this job. process_list_t processes; - // The tree containing this job. + // The group containing this job. // This is never null and not changed after construction. - job_tree_ref_t job_tree{}; + job_group_ref_t group{}; /// Process group ID for the process group that this job is running in. /// Set to a nonexistent, non-return-value of getpgid() integer by the constructor // pid_t pgid{INVALID_PID}; - /// \return the pgid for the job, based on the job tree. + /// \return the pgid for the job, based on the job group. /// This may be none if the job consists of just internal fish functions or builtins. /// This may also be fish itself. - maybe_t get_pgid() const { return job_tree->get_pgid(); } + maybe_t get_pgid() const { return group->get_pgid(); } /// The id of this job. /// This is user-visible, is recycled, and may be -1. - job_id_t job_id() const { return job_tree->get_id(); } + job_id_t job_id() const { return group->get_id(); } /// A non-user-visible, never-recycled job ID. const internal_job_id_t internal_job_id;