Mercurial > vim
changeset 10317:25cc0021a8d7 v8.0.0054
commit https://github.com/vim/vim/commit/fb63090b62801d718fe7e1f44407358404c08724
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Oct 29 14:55:00 2016 +0200
patch 8.0.0054
Problem: On Windows job_stop() stops cmd.exe, not the processes it runs.
(Linwei)
Solution: Iterate over all processes and terminate the one where the parent
is the job process. Now only when there is no job object.
(Yasuhiro Matsumoto, closes #1203)
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sat, 29 Oct 2016 15:00:04 +0200 |
parents | ca4163abc040 |
children | a0279bd5d079 |
files | src/os_win32.c src/version.c |
diffstat | 2 files changed, 50 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/src/os_win32.c +++ b/src/os_win32.c @@ -50,6 +50,10 @@ # endif #endif +#ifdef FEAT_JOB_CHANNEL +# include <tlhelp32.h> +#endif + #ifdef __MINGW32__ # ifndef FROM_LEFT_1ST_BUTTON_PRESSED # define FROM_LEFT_1ST_BUTTON_PRESSED 0x0001 @@ -5020,6 +5024,48 @@ mch_detect_ended_job(job_T *job_list) return NULL; } + static BOOL +terminate_all(HANDLE process, int code) +{ + PROCESSENTRY32 pe; + HANDLE h = INVALID_HANDLE_VALUE; + DWORD pid = GetProcessId(process); + + if (pid != 0) + { + h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (h != INVALID_HANDLE_VALUE) + { + pe.dwSize = sizeof(PROCESSENTRY32); + if (!Process32First(h, &pe)) + goto theend; + + do + { + if (pe.th32ParentProcessID == pid) + { + HANDLE ph = OpenProcess( + PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID); + if (ph != NULL) + { + terminate_all(ph, code); + CloseHandle(ph); + } + } + } while (Process32Next(h, &pe)); + + CloseHandle(h); + } + } + +theend: + return TerminateProcess(process, code); +} + +/* + * Send a (deadly) signal to "job". + * Return FAIL if it didn't work. + */ int mch_stop_job(job_T *job, char_u *how) { @@ -5027,10 +5073,10 @@ mch_stop_job(job_T *job, char_u *how) if (STRCMP(how, "term") == 0 || STRCMP(how, "kill") == 0 || *how == NUL) { + /* deadly signal */ if (job->jv_job_object != NULL) return TerminateJobObject(job->jv_job_object, 0) ? OK : FAIL; - else - return TerminateProcess(job->jv_proc_info.hProcess, 0) ? OK : FAIL; + return terminate_all(job->jv_proc_info.hProcess, 0) ? OK : FAIL; } if (!AttachConsole(job->jv_proc_info.dwProcessId))