changeset 10304:179794481db4 v8.0.0048

commit https://github.com/vim/vim/commit/a350bab042605422304161df462b173ffa31dcb9 Author: Bram Moolenaar <Bram@vim.org> Date: Thu Oct 27 16:46:53 2016 +0200 patch 8.0.0048 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. (Yasuhiro Matsumoto, closes #1184)
author Christian Brabandt <cb@256bit.org>
date Thu, 27 Oct 2016 17:00:04 +0200
parents 9b3b448e538e
children cc0b395eaa88
files src/os_win32.c src/structs.h src/version.c
diffstat 3 files changed, 45 insertions(+), 26 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
@@ -4796,7 +4800,6 @@ mch_start_job(char *cmd, job_T *job, job
 {
     STARTUPINFO		si;
     PROCESS_INFORMATION	pi;
-    HANDLE		jo;
     SECURITY_ATTRIBUTES saAttr;
     channel_T		*channel = NULL;
     HANDLE		ifd[2];
@@ -4821,13 +4824,6 @@ mch_start_job(char *cmd, job_T *job, job
     efd[0] = INVALID_HANDLE_VALUE;
     efd[1] = INVALID_HANDLE_VALUE;
 
-    jo = CreateJobObject(NULL, NULL);
-    if (jo == NULL)
-    {
-	job->jv_status = JOB_FAILED;
-	goto failed;
-    }
-
     ZeroMemory(&pi, sizeof(pi));
     ZeroMemory(&si, sizeof(si));
     si.cb = sizeof(si);
@@ -4912,28 +4908,17 @@ mch_start_job(char *cmd, job_T *job, job
     }
 
     if (!vim_create_process(cmd, TRUE,
-	    CREATE_SUSPENDED |
 	    CREATE_DEFAULT_ERROR_MODE |
 	    CREATE_NEW_PROCESS_GROUP |
 	    CREATE_NEW_CONSOLE,
 	    &si, &pi))
     {
-	CloseHandle(jo);
 	job->jv_status = JOB_FAILED;
 	goto failed;
     }
 
-    if (!AssignProcessToJobObject(jo, pi.hProcess))
-    {
-	/* if failing, switch the way to terminate
-	 * process with TerminateProcess. */
-	CloseHandle(jo);
-	jo = NULL;
-    }
-    ResumeThread(pi.hThread);
     CloseHandle(pi.hThread);
     job->jv_proc_info = pi;
-    job->jv_job_object = jo;
     job->jv_status = JOB_STARTED;
 
     CloseHandle(ifd[0]);
@@ -5020,6 +5005,44 @@ 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)
+	    goto theend;
+
+	pe.dwSize = sizeof(PROCESSENTRY32);
+	if (Process32First(h, &pe))
+	{
+	    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);
+}
+
     int
 mch_stop_job(job_T *job, char_u *how)
 {
@@ -5027,10 +5050,7 @@ mch_stop_job(job_T *job, char_u *how)
 
     if (STRCMP(how, "term") == 0 || STRCMP(how, "kill") == 0 || *how == NUL)
     {
-	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))
@@ -5051,8 +5071,6 @@ mch_clear_job(job_T *job)
 {
     if (job->jv_status != JOB_FAILED)
     {
-	if (job->jv_job_object != NULL)
-	    CloseHandle(job->jv_job_object);
 	CloseHandle(job->jv_proc_info.hProcess);
     }
 }
--- a/src/structs.h
+++ b/src/structs.h
@@ -1437,7 +1437,6 @@ struct jobvar_S
 #endif
 #ifdef WIN32
     PROCESS_INFORMATION	jv_proc_info;
-    HANDLE		jv_job_object;
 #endif
     jobstatus_T	jv_status;
     char_u	*jv_stoponexit; /* allocated */
--- a/src/version.c
+++ b/src/version.c
@@ -765,6 +765,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    48,
+/**/
     47,
 /**/
     46,