Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
jobs: child proc must have a separate process-group
UV_PROCESS_DETACHED compels libuv:uv__process_child_init() to call setsid() in the child just after fork(). That ensures the process and its descendants are grouped in a separate session (and process group). The following jobstart() call correctly groups `sh` and `sleep` in a new session (and process-group), where `sh` is the "session leader" (and process-group leader): :call jobstart(['sh','-c','sleep 60']) SESN PGRP PID PPID USER Command 30383 30383 30383 3620 vagrant │ ├─ -bash 30383 31432 31432 30383 vagrant │ │ └─ nvim -u NORC 30383 31432 31433 30383 vagrant │ │ ├─ nvim -u NORC 8105 8105 8105 31432 vagrant │ │ └─ sh -c sleep 60 8105 8105 8106 8105 vagrant │ │ └─ sleep 60 closes neovim#6530 ref: https://stackoverflow.com/q/1046933 ref: https://unix.stackexchange.com/a/404065 Helped-by: Marco Hinz <mh.codebro+github@gmail.com> Discussion ------------------------------------------------------------------------ On my linux box before this patch, the termclose_spec.lua:'kills job trapping SIGTERM' test indirectly causes cmake/busted to wait for 60s. That's because the test spawns a `sleep 60` descendant process which hangs around even after nvim exits: nvim killed the parent PID, but not PGID (process-group), so the grandchild "reparented" to init (PID 1). Session contains processes (and process-groups) which are logically part of the same "login session". Process-group is a set of logically/informally-related processes within a session; for example, shells assign a process group to each "job". Session IDs and PGIDs both have type pid_t (like PIDs). These OS-level mechanisms are, as usual, legacy accidents whose purpose is upheld by convention and folklore. We can use session-level grouping (setsid), or we could use process-group-level grouping (setpgid). Vim uses setsid() if available, otherwise setpgid(0,0). Windows ------------------------------------------------------------------------ UV_PROCESS_DETACHED on win32 sets CREATE_NEW_PROCESS_GROUP flag. But uv_kill() does not kill the process-group: nodejs/node#3617 Ideas: - Set UV_PROCESS_WINDOWS_HIDE (CREATE_NEW_PROCESS_GROUP), then call GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid) - Maybe won't work because MSDN says "Only processes that share the same console as the calling process receive the signal." https://docs.microsoft.com/en-us/windows/console/generateconsolectrlevent But CREATE_NEW_PROCESS_GROUP creates a new console ... ref https://stackoverflow.com/q/1453520 - Group processes within a "job". libuv does that *globally* for non-detached processes: uv__init_global_job_handle. - Iterate through CreateToolhelp32Snapshot(). - https://stackoverflow.com/q/1173342 - Vim does this, see terminate_all() TODO ------------------------------------------------------------------------ - test-case from neovim#6530: call jobstop(jobstart('/bin/bash -c ''trap true SIGTERM; sleep 20000000000000''')) - win: iterate through children - implement nvim_get_proc_children(): libuv/libuv#836 - remove useless "watched children" (`loop->children`) from `children_kill_cb` ? - get parent process id: uv_os_getppid() (libuv 1.16+)
- Loading branch information