mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-03-15 23:22:53 +08:00
Remove job_flags as an enum, just use a struct
This removes an over-complicated flag implementation, replacing it with just a plain struct.
This commit is contained in:
parent
4c63ae357a
commit
cc1c973025
@ -31,7 +31,7 @@ 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());
|
||||
parser.job_promote(j);
|
||||
j->set_flag(job_flag_t::FOREGROUND, false);
|
||||
j->mut_flags().foreground = false;
|
||||
j->continue_job(parser, true, j->is_stopped());
|
||||
return STATUS_CMD_OK;
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ static int disown_job(const wchar_t *cmd, parser_t &parser, io_streams_t &stream
|
||||
// We cannot directly remove the job from the jobs() list as `disown` might be called
|
||||
// within the context of a subjob which will cause the parent job to crash in exec_job().
|
||||
// Instead, we set a flag and the parser removes the job from the jobs list later.
|
||||
j->set_flag(job_flag_t::DISOWN_REQUESTED, true);
|
||||
j->mut_flags().disown_requested = true;
|
||||
add_disowned_pgid(j->pgid);
|
||||
|
||||
return STATUS_CMD_OK;
|
||||
|
@ -105,7 +105,7 @@ int builtin_fg(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
||||
reader_write_title(job->command(), parser);
|
||||
|
||||
parser.job_promote(job);
|
||||
job->set_flag(job_flag_t::FOREGROUND, true);
|
||||
job->mut_flags().foreground = true;
|
||||
|
||||
job->continue_job(parser, true, job->is_stopped());
|
||||
return STATUS_CMD_OK;
|
||||
|
14
src/exec.cpp
14
src/exec.cpp
@ -316,7 +316,7 @@ void internal_exec(env_stack_t &vars, job_t *j, const io_chain_t &all_ios) {
|
||||
// launch_process _never_ returns.
|
||||
launch_process_nofork(vars, j->processes.front().get());
|
||||
} else {
|
||||
j->set_flag(job_flag_t::CONSTRUCTED, true);
|
||||
j->mut_flags().constructed = true;
|
||||
j->processes.front()->completed = 1;
|
||||
return;
|
||||
}
|
||||
@ -563,15 +563,15 @@ static bool exec_internal_builtin_proc(parser_t &parser, const std::shared_ptr<j
|
||||
// way, the builtin does not need to know what job it is part of. It could
|
||||
// probably figure that out by walking the job list, but it seems more robust to
|
||||
// make exec handle things.
|
||||
const int fg = j->is_foreground();
|
||||
j->set_flag(job_flag_t::FOREGROUND, false);
|
||||
const bool fg = j->is_foreground();
|
||||
j->mut_flags().foreground = false;
|
||||
|
||||
// Note this call may block for a long time, while the builtin performs I/O.
|
||||
p->status = builtin_run(parser, j->pgid, p->get_argv(), streams);
|
||||
|
||||
// Restore the fg flag, which is temporarily set to false during builtin
|
||||
// execution so as not to confuse some job-handling builtins.
|
||||
j->set_flag(job_flag_t::FOREGROUND, fg);
|
||||
j->mut_flags().foreground = fg;
|
||||
|
||||
return true; // "success"
|
||||
}
|
||||
@ -1062,7 +1062,7 @@ bool exec_job(parser_t &parser, shared_ptr<job_t> j) {
|
||||
// Perhaps inherit our parent's pgid and job control flag.
|
||||
if (parent_job && parent_job->pgid != INVALID_PID) {
|
||||
j->pgid = parent_job->pgid;
|
||||
j->set_flag(job_flag_t::JOB_CONTROL, true);
|
||||
j->mut_flags().job_control = true;
|
||||
}
|
||||
|
||||
if (j->pgid == INVALID_PID && should_claim_process_group_for_job(j)) {
|
||||
@ -1085,7 +1085,7 @@ bool exec_job(parser_t &parser, shared_ptr<job_t> j) {
|
||||
internal_exec(parser.vars(), j.get(), all_ios);
|
||||
// internal_exec only returns if it failed to set up redirections.
|
||||
// In case of an successful exec, this code is not reached.
|
||||
bool status = j->get_flag(job_flag_t::NEGATE) ? 0 : 1;
|
||||
bool status = j->flags().negate ? 0 : 1;
|
||||
parser.set_last_statuses(statuses_t::just(status));
|
||||
return false;
|
||||
}
|
||||
@ -1149,7 +1149,7 @@ bool exec_job(parser_t &parser, shared_ptr<job_t> j) {
|
||||
FLOGF(exec_job_exec, L"Executed job %d from command '%ls' with pgrp %d", j->job_id,
|
||||
j->command_wcstr(), j->pgid);
|
||||
|
||||
j->set_flag(job_flag_t::CONSTRUCTED, true);
|
||||
j->mut_flags().constructed = true;
|
||||
if (!j->is_foreground()) {
|
||||
parser.vars().set_one(L"last_pid", ENV_GLOBAL, to_string(j->pgid));
|
||||
}
|
||||
|
@ -1029,7 +1029,8 @@ bool parse_execution_context_t::determine_io_chain(tnode_t<g::arguments_or_redir
|
||||
|
||||
parse_execution_result_t parse_execution_context_t::populate_not_process(
|
||||
job_t *job, process_t *proc, tnode_t<g::not_statement> not_statement) {
|
||||
job->set_flag(job_flag_t::NEGATE, !job->get_flag(job_flag_t::NEGATE));
|
||||
auto &flags = job->mut_flags();
|
||||
flags.negate = !flags.negate;
|
||||
return this->populate_job_process(job, proc,
|
||||
not_statement.require_get_child<g::statement, 1>());
|
||||
}
|
||||
@ -1263,8 +1264,8 @@ parse_execution_result_t parse_execution_context_t::run_1_job(tnode_t<g::job> jo
|
||||
shared_ptr<job_t> job = std::make_shared<job_t>(acquire_job_id(), props, block_io, parent_job);
|
||||
job->tmodes = tmodes;
|
||||
|
||||
job->set_flag(job_flag_t::FOREGROUND, !job_node_is_background(job_node));
|
||||
job->set_flag(job_flag_t::JOB_CONTROL, wants_job_control);
|
||||
job->mut_flags().foreground = !job_node_is_background(job_node);
|
||||
job->mut_flags().job_control = wants_job_control;
|
||||
|
||||
// We are about to populate a job. One possible argument to the job is a command substitution
|
||||
// which may be interested in the job that's populating it, via '--on-job-exit caller'. Record
|
||||
|
16
src/proc.cpp
16
src/proc.cpp
@ -177,10 +177,6 @@ bool job_t::job_chain_is_fully_constructed() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void job_t::set_flag(job_flag_t flag, bool set) { this->flags.set(flag, set); }
|
||||
|
||||
bool job_t::get_flag(job_flag_t flag) const { return this->flags.get(flag); }
|
||||
|
||||
bool job_t::signal(int signal) {
|
||||
// Presumably we are distinguishing between the two cases below because we do
|
||||
// not want to send ourselves the signal in question in case the job shares
|
||||
@ -211,7 +207,7 @@ statuses_t job_t::get_statuses() const {
|
||||
st.pipestatus.push_back(p->status.status_value());
|
||||
}
|
||||
int laststatus = st.pipestatus.back();
|
||||
st.status = (get_flag(job_flag_t::NEGATE) ? !laststatus : laststatus);
|
||||
st.status = flags().negate ? !laststatus : laststatus;
|
||||
return st;
|
||||
}
|
||||
|
||||
@ -453,7 +449,7 @@ void remove_disowned_jobs(job_list_t &jobs) {
|
||||
auto iter = jobs.begin();
|
||||
while (iter != jobs.end()) {
|
||||
const auto &j = *iter;
|
||||
if (j->get_flag(job_flag_t::DISOWN_REQUESTED) && j->job_chain_is_fully_constructed()) {
|
||||
if (j->flags().disown_requested && j->job_chain_is_fully_constructed()) {
|
||||
iter = jobs.erase(iter);
|
||||
} else {
|
||||
++iter;
|
||||
@ -484,7 +480,7 @@ static bool try_clean_process_in_job(process_t *p, job_t *j, std::vector<event_t
|
||||
}
|
||||
|
||||
int proc_is_job = (p->is_first_in_job && p->is_last_in_job);
|
||||
if (proc_is_job) j->set_flag(job_flag_t::NOTIFIED, true);
|
||||
if (proc_is_job) j->mut_flags().notified = true;
|
||||
|
||||
// Handle signals other than SIGPIPE.
|
||||
// Always report crashes.
|
||||
@ -535,7 +531,7 @@ static bool try_clean_process_in_job(process_t *p, job_t *j, std::vector<event_t
|
||||
/// \return whether this job wants a status message printed when it stops or completes.
|
||||
static bool job_wants_message(const shared_ptr<job_t> &j) {
|
||||
// Did we already print a status message?
|
||||
if (j->get_flag(job_flag_t::NOTIFIED)) return false;
|
||||
if (j->flags().notified) return false;
|
||||
|
||||
// Do we just skip notifications?
|
||||
if (j->skip_notification()) return false;
|
||||
@ -598,7 +594,7 @@ static bool process_clean_after_marking(parser_t &parser, bool allow_interactive
|
||||
// Print the message if we need to.
|
||||
if (job_wants_message(j) && (j->is_completed() || j->is_stopped())) {
|
||||
print_job_status(j.get(), j->is_completed() ? JOB_ENDED : JOB_STOPPED);
|
||||
j->set_flag(job_flag_t::NOTIFIED, true);
|
||||
j->mut_flags().notified = true;
|
||||
printed = true;
|
||||
}
|
||||
|
||||
@ -864,7 +860,7 @@ static bool terminal_return_from_job(job_t *j, int restore_attrs) {
|
||||
void job_t::continue_job(parser_t &parser, bool reclaim_foreground_pgrp, bool send_sigcont) {
|
||||
// Put job first in the job list.
|
||||
parser.job_promote(this);
|
||||
set_flag(job_flag_t::NOTIFIED, false);
|
||||
mut_flags().notified = false;
|
||||
|
||||
FLOGF(proc_job_run, L"%ls job %d, gid %d (%ls), %ls, %ls",
|
||||
send_sigcont ? L"Continue" : L"Start", job_id, pgid, command_wcstr(),
|
||||
|
64
src/proc.h
64
src/proc.h
@ -17,7 +17,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include "common.h"
|
||||
#include "enum_set.h"
|
||||
#include "event.h"
|
||||
#include "io.h"
|
||||
#include "parse_tree.h"
|
||||
@ -252,30 +251,6 @@ class process_t {
|
||||
typedef std::unique_ptr<process_t> process_ptr_t;
|
||||
typedef std::vector<process_ptr_t> process_list_t;
|
||||
|
||||
/// Constants for the flag variable in the job struct.
|
||||
enum class job_flag_t {
|
||||
/// Whether the user has been told about stopped job.
|
||||
NOTIFIED,
|
||||
/// Whether this job is in the foreground.
|
||||
FOREGROUND,
|
||||
/// Whether the specified job is completely constructed, i.e. completely parsed, and every
|
||||
/// process in the job has been forked, etc.
|
||||
CONSTRUCTED,
|
||||
/// Whether the exit status should be negated. This flag can only be set by the not builtin.
|
||||
NEGATE,
|
||||
/// Whether the job is under job control, i.e. has its own pgrp.
|
||||
JOB_CONTROL,
|
||||
/// This job is disowned, and should be removed from the active jobs list.
|
||||
DISOWN_REQUESTED,
|
||||
|
||||
JOB_FLAG_COUNT
|
||||
};
|
||||
|
||||
template <>
|
||||
struct enum_info_t<job_flag_t> {
|
||||
static constexpr auto count = job_flag_t::JOB_FLAG_COUNT;
|
||||
};
|
||||
|
||||
typedef int job_id_t;
|
||||
job_id_t acquire_job_id(void);
|
||||
void release_job_id(job_id_t jobid);
|
||||
@ -384,15 +359,36 @@ class job_t {
|
||||
/// stops.
|
||||
struct termios tmodes {};
|
||||
|
||||
/// Bitset containing information about the job. A combination of the JOB_* constants.
|
||||
enum_set_t<job_flag_t> flags{};
|
||||
/// Flags associated with the job.
|
||||
struct flags_t {
|
||||
/// Whether the user has been told about stopped job.
|
||||
bool notified{false};
|
||||
|
||||
// Get and set flags
|
||||
bool get_flag(job_flag_t flag) const;
|
||||
void set_flag(job_flag_t flag, bool set);
|
||||
/// Whether this job is in the foreground.
|
||||
bool foreground{false};
|
||||
|
||||
/// Whether the specified job is completely constructed, i.e. completely parsed, and every
|
||||
/// process in the job has been forked, etc.
|
||||
bool constructed{false};
|
||||
|
||||
/// Whether the exit status should be negated. This flag can only be set by the not builtin.
|
||||
bool negate{false};
|
||||
|
||||
/// Whether the job is under job control, i.e. has its own pgrp.
|
||||
bool job_control{false};
|
||||
|
||||
/// This job is disowned, and should be removed from the active jobs list.
|
||||
bool disown_requested{false};
|
||||
} job_flags{};
|
||||
|
||||
/// Access the job flags.
|
||||
const flags_t &flags() const { return job_flags; }
|
||||
|
||||
/// Access mutable job flags.
|
||||
flags_t &mut_flags() { return job_flags; }
|
||||
|
||||
/// \return if we want job control.
|
||||
bool wants_job_control() const { return get_flag(job_flag_t::JOB_CONTROL); }
|
||||
bool wants_job_control() const { return flags().job_control; }
|
||||
|
||||
/// \return if this job should own the terminal when it runs.
|
||||
bool should_claim_terminal() const { return properties.wants_terminal && is_foreground(); }
|
||||
@ -406,16 +402,16 @@ class job_t {
|
||||
|
||||
// Helper functions to check presence of flags on instances of jobs
|
||||
/// The job has been fully constructed, i.e. all its member processes have been launched
|
||||
bool is_constructed() const { return get_flag(job_flag_t::CONSTRUCTED); }
|
||||
bool is_constructed() const { return flags().constructed; }
|
||||
/// The job was launched in the foreground and has control of the terminal
|
||||
bool is_foreground() const { return get_flag(job_flag_t::FOREGROUND); }
|
||||
bool is_foreground() const { return flags().foreground; }
|
||||
/// The job is complete, i.e. all its member processes have been reaped
|
||||
bool is_completed() const;
|
||||
/// The job is in a stopped state
|
||||
bool is_stopped() const;
|
||||
/// The job is OK to be externally visible, e.g. to the user via `jobs`
|
||||
bool is_visible() const {
|
||||
return !is_completed() && is_constructed() && !get_flag(job_flag_t::DISOWN_REQUESTED);
|
||||
return !is_completed() && is_constructed() && !flags().disown_requested;
|
||||
};
|
||||
bool skip_notification() const { return properties.skip_notification; }
|
||||
bool from_event_handler() const { return properties.from_event_handler; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user