mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-30 14:53:11 +00:00
Make disowned pid reaping thread-safe
This commit is contained in:
parent
4d929720ce
commit
84febe8f2e
1 changed files with 15 additions and 9 deletions
24
src/proc.cpp
24
src/proc.cpp
|
@ -292,7 +292,7 @@ typedef unsigned int process_generation_count_t;
|
||||||
|
|
||||||
/// A list of pids/pgids that have been disowned. They are kept around until either they exit or
|
/// A list of pids/pgids that have been disowned. They are kept around until either they exit or
|
||||||
/// we exit. Poll these from time-to-time to prevent zombie processes from happening (#5342).
|
/// we exit. Poll these from time-to-time to prevent zombie processes from happening (#5342).
|
||||||
static std::vector<pid_t> s_disowned_pids;
|
static owning_lock<std::vector<pid_t>> s_disowned_pids;
|
||||||
|
|
||||||
void add_disowned_pgid(pid_t pgid) {
|
void add_disowned_pgid(pid_t pgid) {
|
||||||
// NEVER add our own (or an invalid) pgid as they are not unique to only
|
// NEVER add our own (or an invalid) pgid as they are not unique to only
|
||||||
|
@ -300,10 +300,21 @@ void add_disowned_pgid(pid_t pgid) {
|
||||||
if (pgid != getpgrp() && pgid > 0) {
|
if (pgid != getpgrp() && pgid > 0) {
|
||||||
// waitpid(2) is signalled to wait on a process group rather than a
|
// waitpid(2) is signalled to wait on a process group rather than a
|
||||||
// process id by using the negative of its value.
|
// process id by using the negative of its value.
|
||||||
s_disowned_pids.push_back(pgid * -1);
|
s_disowned_pids.acquire()->push_back(pgid * -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reap any pids in our disowned list that have exited. This is used to avoid zombies.
|
||||||
|
static void reap_disowned_pids() {
|
||||||
|
auto disowned_pids = s_disowned_pids.acquire();
|
||||||
|
auto try_reap1 = [](pid_t pid) {
|
||||||
|
int status;
|
||||||
|
return waitpid(pid, &status, WNOHANG) > 0;
|
||||||
|
};
|
||||||
|
disowned_pids->erase(std::remove_if(disowned_pids->begin(), disowned_pids->end(), try_reap1),
|
||||||
|
disowned_pids->end());
|
||||||
|
}
|
||||||
|
|
||||||
/// See if any reapable processes have exited, and mark them accordingly.
|
/// 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
|
/// \param block_ok if no reapable processes have exited, block until one is (or until we receive a
|
||||||
/// signal).
|
/// signal).
|
||||||
|
@ -374,13 +385,8 @@ static void process_mark_finished_children(parser_t &parser, bool block_ok) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Poll disowned processes/process groups, but do nothing with the result. Only used to avoid
|
// Remove any zombies.
|
||||||
// zombie processes. Entries have already been converted to negative for process groups.
|
reap_disowned_pids();
|
||||||
int status;
|
|
||||||
s_disowned_pids.erase(
|
|
||||||
std::remove_if(s_disowned_pids.begin(), s_disowned_pids.end(),
|
|
||||||
[&status](pid_t pid) { return waitpid(pid, &status, WNOHANG) > 0; }),
|
|
||||||
s_disowned_pids.end());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a command like "cat file", truncate it to a reasonable length.
|
/// Given a command like "cat file", truncate it to a reasonable length.
|
||||||
|
|
Loading…
Reference in a new issue