mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-01-23 06:00:46 +08:00
Work around for Cygwin's broken job control resolving fish 3.0 hang
(cherry picked from commit d1913f0df0
)
This commit is contained in:
parent
e462c6fe0e
commit
91ac0f1b18
|
@ -19,6 +19,11 @@ if (CMAKE_HOST_SYSTEM_VERSION MATCHES ".*-Microsoft")
|
|||
SET(WSL 1)
|
||||
endif()
|
||||
|
||||
# Detect Cygwin.
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "CYGWIN_NT.*")
|
||||
SET(CYGWIN 1)
|
||||
endif()
|
||||
|
||||
# Set up the config.h file.
|
||||
SET(PACKAGE_NAME "fish")
|
||||
SET(PACKAGE_TARNAME "fish")
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
/* Define to 1 if compiled on WSL */
|
||||
#cmakedefine WSL 1
|
||||
|
||||
/* Define to 1 if complied under Cygwin */
|
||||
#cmakedefine CYGWIN 1
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#cmakedefine HAVE_CLOCK_GETTIME 1
|
||||
|
||||
|
|
|
@ -976,6 +976,15 @@ constexpr bool is_windows_subsystem_for_linux() {
|
|||
#endif
|
||||
}
|
||||
|
||||
/// Detect if we are running under Cygwin or Cgywin64
|
||||
constexpr bool is_cygwin() {
|
||||
#ifdef CYGWIN
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
__attribute__((noinline)) void debug_thread_error(void);
|
||||
}
|
||||
|
|
32
src/proc.cpp
32
src/proc.cpp
|
@ -447,10 +447,34 @@ static bool process_mark_finished_children(bool block_on_fg) {
|
|||
options &= ~WNOHANG;
|
||||
}
|
||||
|
||||
// If the pgid is 0, we need to wait by process because that's invalid.
|
||||
// This happens in firejail for reasons not entirely clear to me.
|
||||
bool wait_by_process = !j->job_chain_is_fully_constructed() || j->pgid == 0;
|
||||
process_list_t::iterator process = j->processes.begin();
|
||||
// Child jobs (produced via execution of functions) share job ids with their not-yet-
|
||||
// fully-constructed parent jobs, so we have to wait on these by individual process id
|
||||
// and not by the shared pgroup. End result is the same, but it just makes more calls
|
||||
// to the kernel.
|
||||
bool wait_by_process = !j->job_chain_is_fully_constructed();
|
||||
|
||||
// Firejail can result in jobs with pgroup 0, in which case we cannot wait by
|
||||
// job id. See discussion in #5295.
|
||||
if (j->pgid == 0) {
|
||||
wait_by_process = true;
|
||||
}
|
||||
|
||||
// Cygwin does some voodoo with regards to process management that I do not understand, but
|
||||
// long story short, we cannot reap processes by their pgroup. The way child processes are
|
||||
// launched under Cygwin is... weird, and outwardly they do not appear to retain information
|
||||
// about their parent process when viewed in Task Manager. Waiting on processes by their
|
||||
// pgroup results in never reaping any, so we just wait on them by process id instead.
|
||||
if (is_cygwin()) {
|
||||
wait_by_process = true;
|
||||
}
|
||||
|
||||
// When waiting on processes individually in a pipeline, we need to enumerate in reverse
|
||||
// order so that the first process we actually wait on (i.e. ~WNOHANG) is the last process
|
||||
// in the IO chain, because that's the one that controls the lifetime of the foreground job
|
||||
// - as long as it is still running, we are in the background and once it exits or is
|
||||
// killed, all previous jobs in the IO pipeline must necessarily terminate as well.
|
||||
auto process = j->processes.begin();
|
||||
|
||||
// waitpid(2) returns 1 process each time, we need to keep calling it until we've reaped all
|
||||
// children of the pgrp in question or else we can't reset the dirty_state flag. In all
|
||||
// cases, calling waitpid(2) is faster than potentially calling select_try() on a process
|
||||
|
|
Loading…
Reference in New Issue
Block a user