Orphan background tasks to work around terminals being sensitive to unreaped processes

When a command like "long-running-command &" exits, the resulting SIGCHLD
is queued in the topic monitor. We do not process this signal immediately
but only after e.g. the next command has finished. Only then do we reap the
child process.

Some terminals, such as Terminal.app, refuse to close when there are unreaped
processes associated with the terminal -- as in, having the same session ID,
see setsid(3).

In future, we might want to reap proactively.

For now, apply an isolated workaround: instead of taking care of a child
process, double-fork to create an orphaned process. Since the orphan will
be reaped by PID 1, we can eventually close Terminal.app without it asking
for confirmation.

	/bin/sh -c '( "$@" ) >/dev/null 2>&1 &' -- cmd arg1 arg2

This fix confines the problem to the period during which a background process
is running. To complete the fix, we would need to call setsid to detach the
background process from a controlling terminal. That seems to be desirable
however macOS does provide a setsid utility.

	setsid cmd arg1 arg2 >/dev/null 2>&1

Fixes #11181

(cherry picked from commit e015956de7)
This commit is contained in:
Johannes Altmanninger
2025-02-28 03:58:51 +01:00
parent f96b9c53ce
commit c06830ccf2
4 changed files with 5 additions and 9 deletions

View File

@@ -40,8 +40,7 @@ if test $status -eq 0 -a (count $sysver) -eq 3
if test $age -ge $max_age
test -d "$dir" || mkdir -m 700 -p $dir
/usr/libexec/makewhatis -o "$whatis" (/usr/bin/manpath | string split : | xargs realpath) >/dev/null 2>&1 </dev/null &
disown $last_pid
/bin/sh -c '( "$@" ) >/dev/null 2>&1 </dev/null &' -- /usr/libexec/makewhatis -o "$whatis" (/usr/bin/manpath | string split : | xargs realpath)
end
end
else

View File

@@ -99,9 +99,8 @@ end" >$__fish_config_dir/config.fish
set -l update_args -B $__fish_data_dir/tools/create_manpage_completions.py --manpath --cleanup-in $__fish_user_data_dir/generated_completions --cleanup-in $__fish_cache_dir/generated_completions
if set -l python (__fish_anypython)
# Run python directly in the background and swallow all output
$python $update_args >/dev/null 2>&1 &
# Then disown the job so that it continues to run in case of an early exit (#6269)
disown >/dev/null 2>&1
# Orphan the job so that it continues to run in case of an early exit (#6269)
/bin/sh -c '( "$@" ) >/dev/null 2>&1 &' -- $python $update_args
end
end
end

View File

@@ -180,8 +180,7 @@ if string match -q Darwin -- (uname) && string match -q /usr/bin/git -- (command
else
# git is installed, but on the first run it may be very slow as xcrun needs to populate the cache.
# Kick it off in the background to populate the cache.
/bin/sh -c '/usr/bin/git --version; touch /tmp/__fish_git_ready' &>/dev/null &
disown $last_pid &>/dev/null
/bin/sh -c '( /usr/bin/git --version; touch /tmp/__fish_git_ready ) >/dev/null 2>&1 &'
function __fish_git_prompt_ready
path is /tmp/__fish_git_ready || return 1
# git is ready, erase the function.

View File

@@ -239,8 +239,7 @@ function help --description 'Show help for the fish shell'
# The space before the /c is to prevent msys2 from expanding it to a path
$fish_browser " /c" start $page_url
else if contains -- $fish_browser[1] $graphical_browsers
$fish_browser $page_url &
disown $last_pid >/dev/null 2>&1
/bin/sh -c '( "$@" ) &' -- $fish_browser $page_url
else
$fish_browser $page_url
end