#include "config.h" #include "job_group.h" #include "common.h" #include "fallback.h" // IWYU pragma: keep #include "flog.h" #include "proc.h" // Basic thread safe sorted vector of job IDs in use. // This is deliberately leaked to avoid dtor ordering issues - see #6539. static const auto locked_consumed_job_ids = new owning_lock>(); static job_id_t acquire_job_id() { auto consumed_job_ids = locked_consumed_job_ids->acquire(); // The new job ID should be larger than the largest currently used ID (#6053). job_id_t jid = consumed_job_ids->empty() ? 1 : consumed_job_ids->back() + 1; consumed_job_ids->push_back(jid); return jid; } static void release_job_id(job_id_t jid) { assert(jid > 0); auto consumed_job_ids = locked_consumed_job_ids->acquire(); // Our job ID vector is sorted, but the number of jobs is typically 1 or 2 so a binary search // isn't worth it. auto where = std::find(consumed_job_ids->begin(), consumed_job_ids->end(), jid); assert(where != consumed_job_ids->end() && "Job ID was not in use"); consumed_job_ids->erase(where); } job_group_t::job_group_t(wcstring command, job_id_t job_id, bool job_control, bool wants_terminal) : job_control_(job_control), wants_terminal_(wants_terminal), command_(std::move(command)), job_id_(job_id) {} job_group_t::~job_group_t() { if (job_id_ > 0) { release_job_id(job_id_); } } // static job_group_ref_t job_group_t::create(wcstring command, bool wants_job_id) { job_id_t jid = wants_job_id ? acquire_job_id() : 0; return job_group_ref_t(new job_group_t(std::move(command), jid)); } // static job_group_ref_t job_group_t::create_with_job_control(wcstring command, bool wants_terminal) { return job_group_ref_t(new job_group_t(std::move(command), acquire_job_id(), true /* job_control */, wants_terminal)); } 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 any pgid should always have been set beforehand, since it's set // immediately after thfe first process launches. assert(pgid >= 0 && "invalid pgid"); assert(wants_job_control() && "should not set a pgid for this group"); assert(!pgid_.has_value() && "pgid already set"); pgid_ = pgid; }