Note: the revert is not included into the differential because it is trivial and only hinders readability.
Revert "killpg(): close a race with fork(), part 2" This reverts commits 81a37995c757b4e3ad8a5c699864197fd1ebdcf5 and 565a343ae3a30bc2973182ff8dfd2fa37d7f615f. There is still a leakage of the p_killpg_cnt, some but not all sources of which were identified. Second, and more important, is that there is a fundamental issue with blocked signals having KSI_KILLPG flag set. Queueing of such signal increments p_killpg_cnt, but it cannot be decremented until the signal is delivered. If, for instance, a single-threaded process with blocked signal receives killpg-kill and executes fork(2), the fork enter check returns with ERESTART. And since signal is blocked, the condition cannot be cleared.
sigtd(): prefer non-stopped thread as a target for signal queue This should improve signal delivery latency and better expose the process state to the executing threads.
killpg(): close a race with fork(), part 2 When we are sending terminating signal to the group, killpg() needs to guarantee that all group members are to be terminated (it does not need to ensure that they are terminated on return from killpg()). The pg_killsx change eliminates the largest window there, but still, if a multithreaded process is signalled, the following could happen: - thread 1 is selected for the signal delivery and gets descheduled - thread 2 waits for pg_killsx lock, obtains it and forks - thread 1 continue executing and terminates the process This scenario allows the child to escape still. Fix it by single-threading forking parent if a conflict with pg_killsx is noted. We try to lock pg_killsx without sleeping, and failure to acquire it means that a parallel killpg(2) is executed. Then, stop other threads for running and in particular, receive signals, to avoid the situation explained above.