mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-27 04:05:08 +00:00
Put back process and job exit events
These were removed in f8b2e818ed
under a
belief that they were unused. But they are documented and supported.
This commit is contained in:
parent
43d668bdc8
commit
3dfaa192da
6 changed files with 54 additions and 15 deletions
|
@ -474,7 +474,7 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
// TODO: The generic process-exit event is useless and unused.
|
// TODO: The generic process-exit event is useless and unused.
|
||||||
// Remove this in future.
|
// Remove this in future.
|
||||||
proc_fire_event(L"PROCESS_EXIT", event_type_t::exit, getpid(), exit_status);
|
event_fire(proc_create_event(L"PROCESS_EXIT", event_type_t::exit, getpid(), exit_status));
|
||||||
|
|
||||||
// Trigger any exit handlers.
|
// Trigger any exit handlers.
|
||||||
wcstring_list_t event_args = {to_string(exit_status)};
|
wcstring_list_t event_args = {to_string(exit_status)};
|
||||||
|
|
43
src/proc.cpp
43
src/proc.cpp
|
@ -436,14 +436,14 @@ static void print_job_status(const job_t *j, job_status_t status) {
|
||||||
outp.flush_to(STDOUT_FILENO);
|
outp.flush_to(STDOUT_FILENO);
|
||||||
}
|
}
|
||||||
|
|
||||||
void proc_fire_event(const wchar_t *msg, event_type_t type, pid_t pid, int status) {
|
event_t proc_create_event(const wchar_t *msg, event_type_t type, pid_t pid, int status) {
|
||||||
event_t event{type};
|
event_t event{type};
|
||||||
event.desc.param1.pid = pid;
|
event.desc.param1.pid = pid;
|
||||||
|
|
||||||
event.arguments.push_back(msg);
|
event.arguments.push_back(msg);
|
||||||
event.arguments.push_back(to_string(pid));
|
event.arguments.push_back(to_string(pid));
|
||||||
event.arguments.push_back(to_string(status));
|
event.arguments.push_back(to_string(status));
|
||||||
event_fire(event);
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove all disowned jobs whose job chain is fully constructed (that is, do not erase disowned
|
/// Remove all disowned jobs whose job chain is fully constructed (that is, do not erase disowned
|
||||||
|
@ -461,16 +461,21 @@ void remove_disowned_jobs(job_list_t &jobs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a a process in a job, print the status message for the process as appropriate, and then
|
/// Given a a process in a job, print the status message for the process as appropriate, and then
|
||||||
/// mark the status code so we don't print again. \return true if we printed a status message, false
|
/// mark the status code so we don't print again. Populate any events into \p exit_events.
|
||||||
/// if not.
|
/// \return true if we printed a status message, false if not.
|
||||||
static bool try_clean_process_in_job(process_t *p, job_t *j, bool only_one_job) {
|
static bool try_clean_process_in_job(process_t *p, job_t *j, std::vector<event_t> *exit_events,
|
||||||
|
bool only_one_job) {
|
||||||
if (!p->completed || !p->pid) {
|
if (!p->completed || !p->pid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto s = p->status;
|
auto s = p->status;
|
||||||
// Ignore signal SIGPIPE.We issue it ourselves to the pipe writer when the pipe reader
|
|
||||||
// dies.
|
// Add an exit event.
|
||||||
|
exit_events->push_back(proc_create_event(L"PROCESS_EXIT", event_type_t::exit, p->pid,
|
||||||
|
s.normal_exited() ? s.exit_code() : -1));
|
||||||
|
|
||||||
|
// Ignore SIGPIPE. We issue it ourselves to the pipe writer when the pipe reader dies.
|
||||||
if (!s.signal_exited() || s.signal_code() == SIGPIPE) {
|
if (!s.signal_exited() || s.signal_code() == SIGPIPE) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -566,6 +571,12 @@ static bool process_clean_after_marking(bool allow_interactive) {
|
||||||
// If we ever drop the `static bool locked` above, this should be changed to a local or
|
// If we ever drop the `static bool locked` above, this should be changed to a local or
|
||||||
// thread-local vector instead of a static vector. It is only static to reduce heap allocations.
|
// thread-local vector instead of a static vector. It is only static to reduce heap allocations.
|
||||||
static std::vector<shared_ptr<job_t>> erase_list;
|
static std::vector<shared_ptr<job_t>> erase_list;
|
||||||
|
|
||||||
|
// Accumulate exit events into a new list, which we fire after the list manipulation is
|
||||||
|
// complete.
|
||||||
|
std::vector<event_t> exit_events;
|
||||||
|
|
||||||
|
// Print status messages for completed or stopped jobs.
|
||||||
const bool only_one_job = jobs().size() == 1;
|
const bool only_one_job = jobs().size() == 1;
|
||||||
for (const auto &j : jobs()) {
|
for (const auto &j : jobs()) {
|
||||||
// Skip unconstructed jobs.
|
// Skip unconstructed jobs.
|
||||||
|
@ -582,7 +593,7 @@ static bool process_clean_after_marking(bool allow_interactive) {
|
||||||
// Note this may print the message on behalf of the job, affecting the result of
|
// Note this may print the message on behalf of the job, affecting the result of
|
||||||
// job_wants_message().
|
// job_wants_message().
|
||||||
for (process_ptr_t &p : j->processes) {
|
for (process_ptr_t &p : j->processes) {
|
||||||
if (try_clean_process_in_job(p.get(), j.get(), only_one_job)) {
|
if (try_clean_process_in_job(p.get(), j.get(), &exit_events, only_one_job)) {
|
||||||
printed = true;
|
printed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -594,6 +605,16 @@ static bool process_clean_after_marking(bool allow_interactive) {
|
||||||
printed = true;
|
printed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prepare events for completed jobs.
|
||||||
|
if (j->is_completed()) {
|
||||||
|
if (j->pgid != INVALID_PID) {
|
||||||
|
exit_events.push_back(
|
||||||
|
proc_create_event(L"JOB_EXIT", event_type_t::exit, -j->pgid, 0));
|
||||||
|
}
|
||||||
|
exit_events.push_back(
|
||||||
|
proc_create_event(L"JOB_EXIT", event_type_t::job_exit, j->job_id, 0));
|
||||||
|
}
|
||||||
|
|
||||||
// Remove us from the job list if we're complete.
|
// Remove us from the job list if we're complete.
|
||||||
if (j->is_completed()) {
|
if (j->is_completed()) {
|
||||||
erase_list.push_back(j);
|
erase_list.push_back(j);
|
||||||
|
@ -626,9 +647,9 @@ static bool process_clean_after_marking(bool allow_interactive) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only now notify any listeners of the job exit, so that the contract isn't violated
|
// Post pending exit events.
|
||||||
for (const auto &j : erase_list) {
|
for (const auto &evt : exit_events) {
|
||||||
proc_fire_event(L"JOB_EXIT", event_type_t::job_exit, j->job_id, 0);
|
event_fire(evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
erase_list.clear();
|
erase_list.clear();
|
||||||
|
|
|
@ -502,9 +502,8 @@ void proc_update_jiffies();
|
||||||
/// job is in the foreground, that every process is in a valid state, etc.
|
/// job is in the foreground, that every process is in a valid state, etc.
|
||||||
void proc_sanity_check();
|
void proc_sanity_check();
|
||||||
|
|
||||||
/// Send a process/job exit event notification. This function is a convenience wrapper around
|
/// Create a process/job exit event notification.
|
||||||
/// event_fire().
|
event_t proc_create_event(const wchar_t *msg, event_type_t type, pid_t pid, int status);
|
||||||
void proc_fire_event(const wchar_t *msg, event_type_t type, pid_t pid, int status);
|
|
||||||
|
|
||||||
/// Initializations.
|
/// Initializations.
|
||||||
void proc_init();
|
void proc_init();
|
||||||
|
|
|
@ -21,3 +21,12 @@ function foo
|
||||||
jobs -c
|
jobs -c
|
||||||
end
|
end
|
||||||
foo
|
foo
|
||||||
|
|
||||||
|
# Verify we observe job exit events
|
||||||
|
sleep 1 &
|
||||||
|
set sleep_job $last_pid
|
||||||
|
function sleep_done_$sleep_job --on-job-exit $sleep_job
|
||||||
|
/bin/echo "sleep is done"
|
||||||
|
functions --erase sleep_done_$sleep_job
|
||||||
|
end
|
||||||
|
sleep 2
|
||||||
|
|
|
@ -8,3 +8,4 @@ sleep
|
||||||
sleep
|
sleep
|
||||||
Command
|
Command
|
||||||
sleep
|
sleep
|
||||||
|
sleep is done
|
||||||
|
|
|
@ -1,8 +1,17 @@
|
||||||
ALRM received
|
ALRM received
|
||||||
command false:
|
command false:
|
||||||
|
PROCESS_EXIT 1
|
||||||
|
JOB_EXIT 0
|
||||||
command true:
|
command true:
|
||||||
|
PROCESS_EXIT 0
|
||||||
|
JOB_EXIT 0
|
||||||
command false | true:
|
command false | true:
|
||||||
|
PROCESS_EXIT 1
|
||||||
|
PROCESS_EXIT 0
|
||||||
|
JOB_EXIT 0
|
||||||
This is the process whose exit event shuld be blocked
|
This is the process whose exit event shuld be blocked
|
||||||
This should come before the event handler
|
This should come before the event handler
|
||||||
|
PROCESS_EXIT 0
|
||||||
|
JOB_EXIT 0
|
||||||
Now event handler should have run
|
Now event handler should have run
|
||||||
PROCESS_EXIT 0
|
PROCESS_EXIT 0
|
||||||
|
|
Loading…
Reference in a new issue