diff --git a/src/parse_execution.cpp b/src/parse_execution.cpp index 262c31d2a..18e27954b 100644 --- a/src/parse_execution.cpp +++ b/src/parse_execution.cpp @@ -1255,6 +1255,7 @@ end_execution_reason_t parse_execution_context_t::run_1_job(tnode_t job_ job_t::properties_t props{}; props.wants_terminal = wants_job_control && !ld.is_event; + props.initial_background = job_node_is_background(job_node); props.skip_notification = ld.is_subshell || ld.is_block || ld.is_event || !parser->is_interactive(); props.from_event_handler = ld.is_event; @@ -1263,7 +1264,7 @@ end_execution_reason_t parse_execution_context_t::run_1_job(tnode_t job_ shared_ptr job = std::make_shared(props); job->tmodes = tmodes; - job->mut_flags().foreground = !job_node_is_background(job_node); + job->mut_flags().foreground = !props.initial_background; // 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 diff --git a/src/proc.cpp b/src/proc.cpp index 9d912b433..0c7e6a132 100644 --- a/src/proc.cpp +++ b/src/proc.cpp @@ -270,8 +270,8 @@ void job_tree_t::populate_tree_for_job(job_t *job, const job_tree_ref_t &propose // non-placeholder -> we are running as part of a real pipeline // Decide if this job can use the placeholder tree. // This is true if it's a simple foreground execution of an internal proc. - bool can_use_placeholder = - job->is_foreground() && job->processes.size() == 1 && job->processes.front()->is_internal(); + bool can_use_placeholder = !job->is_initially_background() && job->processes.size() == 1 && + job->processes.front()->is_internal(); bool needs_new_tree = false; if (!proposed) { diff --git a/src/proc.h b/src/proc.h index 2c40cac7d..79fe8f3f9 100644 --- a/src/proc.h +++ b/src/proc.h @@ -389,6 +389,11 @@ class job_t { /// Whether the job wants to own the terminal when in the foreground. bool wants_terminal{}; + /// Whether the job had the background ampersand when constructed, e.g. /bin/echo foo & + /// Note that a job may move between foreground and background; this just describes what the + /// initial state should be. + bool initial_background{}; + /// Whether this job was created as part of an event handler. bool from_event_handler{}; @@ -523,6 +528,10 @@ class job_t { /// \return if this job should own the terminal when it runs. bool should_claim_terminal() const { return properties.wants_terminal && is_foreground(); } + /// \return whether this job is initially going to run in the background, because & was + /// specified. + bool is_initially_background() const { return properties.initial_background; } + /// Mark this job as constructed. The job must not have previously been marked as constructed. void mark_constructed();