Ensure that on-process-exit events fire for reaped jobs

This ensures that if a job exits before we have set up the
on-process-exit handler, the handler will still fire.

Fixes #7210
This commit is contained in:
ridiculousfish 2021-05-17 15:22:02 -07:00
parent 60d75e9aa0
commit 6d00ad1045
5 changed files with 37 additions and 3 deletions

View file

@ -45,7 +45,7 @@ Interactive improvements
- Variable ``fish_killring`` containing entries from killring is now available (:issue:`7445`). - Variable ``fish_killring`` containing entries from killring is now available (:issue:`7445`).
- ``fish --private`` prints a note on private mode on startup even if ``$fish_greeting`` is an empty list (:issue:`7974`). - ``fish --private`` prints a note on private mode on startup even if ``$fish_greeting`` is an empty list (:issue:`7974`).
- fish no longer attempts to lock history or universal variable files on remote filesystems, including NFS and SMB. In rare cases, updates to these files may be dropped if separate fish instances modify them simultaneously. (:issue:`7968`). - fish no longer attempts to lock history or universal variable files on remote filesystems, including NFS and SMB. In rare cases, updates to these files may be dropped if separate fish instances modify them simultaneously. (:issue:`7968`).
- ``wait`` works correctly with jobs that have already exited (:issue:`7210`). - ``wait`` and ``on-process-exit`` work correctly with jobs that have already exited (:issue:`7210`).
New or improved bindings New or improved bindings
^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -264,12 +264,30 @@ maybe_t<int> builtin_function(parser_t &parser, io_streams_t &streams,
// Add the function itself. // Add the function itself.
function_add(function_name, opts.description, props, parser.libdata().current_filename); function_add(function_name, opts.description, props, parser.libdata().current_filename);
// Handle wrap targets by creating the appropriate completions.
for (const wcstring &wt : opts.wrap_targets) {
complete_add_wrapper(function_name, wt);
}
// Add any event handlers. // Add any event handlers.
for (const event_description_t &ed : opts.events) { for (const event_description_t &ed : opts.events) {
event_add_handler(std::make_shared<event_handler_t>(ed, function_name)); event_add_handler(std::make_shared<event_handler_t>(ed, function_name));
} }
// Handle wrap targets by creating the appropriate completions. // If there is an --on-process-exit or --on-job-exit event handler for some pid, and that
for (const wcstring &wt : opts.wrap_targets) complete_add_wrapper(function_name, wt); // process has already exited, run it immediately (#7210).
for (const event_description_t &ed : opts.events) {
if (ed.type == event_type_t::exit && ed.param1.pid != EVENT_ANY_PID) {
wait_handle_ref_t wh = parser.get_wait_handles().get_by_pid(abs(ed.param1.pid));
if (wh && wh->completed) {
if (ed.param1.pid > 0) {
event_fire(parser, event_t::process_exit(ed.param1.pid, wh->status));
} else {
event_fire(parser, event_t::job_exit(ed.param1.pid));
}
}
}
}
return STATUS_CMD_OK; return STATUS_CMD_OK;
} }

View file

@ -609,6 +609,7 @@ static void save_wait_handle_for_completed_job(const shared_ptr<job_t> &job,
// Mark all wait handles as complete (but don't create just for this). // Mark all wait handles as complete (but don't create just for this).
for (auto &proc : job->processes) { for (auto &proc : job->processes) {
if (wait_handle_ref_t wh = proc->get_wait_handle(false /* create */)) { if (wait_handle_ref_t wh = proc->get_wait_handle(false /* create */)) {
wh->status = proc->status.status_value();
wh->completed = true; wh->completed = true;
} }
} }

View file

@ -27,6 +27,9 @@ struct wait_handle_t {
/// For example if the process is "/bin/sleep" then this will be 'sleep'. /// For example if the process is "/bin/sleep" then this will be 'sleep'.
wcstring base_name{}; wcstring base_name{};
/// The value appropriate for populating $status, if completed.
int status{0};
/// Set to true when the process is completed. /// Set to true when the process is completed.
bool completed{false}; bool completed{false};
}; };

View file

@ -24,3 +24,15 @@ end
wait true false wait true false
jobs jobs
# CHECK: jobs: There are no jobs # CHECK: jobs: There are no jobs
# Ensure on-process-exit works for exited jobs.
command false &
set pid $last_pid
# Ensure it gets reaped
sleep .1
function waiter --on-process-exit $pid
echo exited $argv
end
# CHECK: exited PROCESS_EXIT {{\d+}} 1