Mercurial > vim
comparison src/os_win32.c @ 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 | c5c15c818bda |
children | 931422d27b69 |
comparison
equal
deleted
inserted
replaced
10303:9b3b448e538e | 10304:179794481db4 |
---|---|
46 | 46 |
47 #ifndef PROTO | 47 #ifndef PROTO |
48 # if defined(FEAT_TITLE) && !defined(FEAT_GUI_W32) | 48 # if defined(FEAT_TITLE) && !defined(FEAT_GUI_W32) |
49 # include <shellapi.h> | 49 # include <shellapi.h> |
50 # endif | 50 # endif |
51 #endif | |
52 | |
53 #ifdef FEAT_JOB_CHANNEL | |
54 # include <tlhelp32.h> | |
51 #endif | 55 #endif |
52 | 56 |
53 #ifdef __MINGW32__ | 57 #ifdef __MINGW32__ |
54 # ifndef FROM_LEFT_1ST_BUTTON_PRESSED | 58 # ifndef FROM_LEFT_1ST_BUTTON_PRESSED |
55 # define FROM_LEFT_1ST_BUTTON_PRESSED 0x0001 | 59 # define FROM_LEFT_1ST_BUTTON_PRESSED 0x0001 |
4794 void | 4798 void |
4795 mch_start_job(char *cmd, job_T *job, jobopt_T *options) | 4799 mch_start_job(char *cmd, job_T *job, jobopt_T *options) |
4796 { | 4800 { |
4797 STARTUPINFO si; | 4801 STARTUPINFO si; |
4798 PROCESS_INFORMATION pi; | 4802 PROCESS_INFORMATION pi; |
4799 HANDLE jo; | |
4800 SECURITY_ATTRIBUTES saAttr; | 4803 SECURITY_ATTRIBUTES saAttr; |
4801 channel_T *channel = NULL; | 4804 channel_T *channel = NULL; |
4802 HANDLE ifd[2]; | 4805 HANDLE ifd[2]; |
4803 HANDLE ofd[2]; | 4806 HANDLE ofd[2]; |
4804 HANDLE efd[2]; | 4807 HANDLE efd[2]; |
4819 ofd[0] = INVALID_HANDLE_VALUE; | 4822 ofd[0] = INVALID_HANDLE_VALUE; |
4820 ofd[1] = INVALID_HANDLE_VALUE; | 4823 ofd[1] = INVALID_HANDLE_VALUE; |
4821 efd[0] = INVALID_HANDLE_VALUE; | 4824 efd[0] = INVALID_HANDLE_VALUE; |
4822 efd[1] = INVALID_HANDLE_VALUE; | 4825 efd[1] = INVALID_HANDLE_VALUE; |
4823 | 4826 |
4824 jo = CreateJobObject(NULL, NULL); | |
4825 if (jo == NULL) | |
4826 { | |
4827 job->jv_status = JOB_FAILED; | |
4828 goto failed; | |
4829 } | |
4830 | |
4831 ZeroMemory(&pi, sizeof(pi)); | 4827 ZeroMemory(&pi, sizeof(pi)); |
4832 ZeroMemory(&si, sizeof(si)); | 4828 ZeroMemory(&si, sizeof(si)); |
4833 si.cb = sizeof(si); | 4829 si.cb = sizeof(si); |
4834 si.dwFlags |= STARTF_USESHOWWINDOW; | 4830 si.dwFlags |= STARTF_USESHOWWINDOW; |
4835 si.wShowWindow = SW_HIDE; | 4831 si.wShowWindow = SW_HIDE; |
4910 if (channel == NULL) | 4906 if (channel == NULL) |
4911 goto failed; | 4907 goto failed; |
4912 } | 4908 } |
4913 | 4909 |
4914 if (!vim_create_process(cmd, TRUE, | 4910 if (!vim_create_process(cmd, TRUE, |
4915 CREATE_SUSPENDED | | |
4916 CREATE_DEFAULT_ERROR_MODE | | 4911 CREATE_DEFAULT_ERROR_MODE | |
4917 CREATE_NEW_PROCESS_GROUP | | 4912 CREATE_NEW_PROCESS_GROUP | |
4918 CREATE_NEW_CONSOLE, | 4913 CREATE_NEW_CONSOLE, |
4919 &si, &pi)) | 4914 &si, &pi)) |
4920 { | 4915 { |
4921 CloseHandle(jo); | |
4922 job->jv_status = JOB_FAILED; | 4916 job->jv_status = JOB_FAILED; |
4923 goto failed; | 4917 goto failed; |
4924 } | 4918 } |
4925 | 4919 |
4926 if (!AssignProcessToJobObject(jo, pi.hProcess)) | |
4927 { | |
4928 /* if failing, switch the way to terminate | |
4929 * process with TerminateProcess. */ | |
4930 CloseHandle(jo); | |
4931 jo = NULL; | |
4932 } | |
4933 ResumeThread(pi.hThread); | |
4934 CloseHandle(pi.hThread); | 4920 CloseHandle(pi.hThread); |
4935 job->jv_proc_info = pi; | 4921 job->jv_proc_info = pi; |
4936 job->jv_job_object = jo; | |
4937 job->jv_status = JOB_STARTED; | 4922 job->jv_status = JOB_STARTED; |
4938 | 4923 |
4939 CloseHandle(ifd[0]); | 4924 CloseHandle(ifd[0]); |
4940 CloseHandle(ofd[1]); | 4925 CloseHandle(ofd[1]); |
4941 if (!use_out_for_err && !use_null_for_err) | 4926 if (!use_out_for_err && !use_null_for_err) |
5018 } | 5003 } |
5019 } | 5004 } |
5020 return NULL; | 5005 return NULL; |
5021 } | 5006 } |
5022 | 5007 |
5008 static BOOL | |
5009 terminate_all(HANDLE process, int code) | |
5010 { | |
5011 PROCESSENTRY32 pe; | |
5012 HANDLE h = INVALID_HANDLE_VALUE; | |
5013 DWORD pid = GetProcessId(process); | |
5014 | |
5015 if (pid != 0) | |
5016 { | |
5017 h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); | |
5018 if (h == INVALID_HANDLE_VALUE) | |
5019 goto theend; | |
5020 | |
5021 pe.dwSize = sizeof(PROCESSENTRY32); | |
5022 if (Process32First(h, &pe)) | |
5023 { | |
5024 do | |
5025 { | |
5026 if (pe.th32ParentProcessID == pid) | |
5027 { | |
5028 HANDLE ph = OpenProcess( | |
5029 PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID); | |
5030 if (ph != NULL) | |
5031 { | |
5032 terminate_all(ph, code); | |
5033 CloseHandle(ph); | |
5034 } | |
5035 } | |
5036 } while (Process32Next(h, &pe)); | |
5037 } | |
5038 | |
5039 CloseHandle(h); | |
5040 } | |
5041 | |
5042 theend: | |
5043 return TerminateProcess(process, code); | |
5044 } | |
5045 | |
5023 int | 5046 int |
5024 mch_stop_job(job_T *job, char_u *how) | 5047 mch_stop_job(job_T *job, char_u *how) |
5025 { | 5048 { |
5026 int ret; | 5049 int ret; |
5027 | 5050 |
5028 if (STRCMP(how, "term") == 0 || STRCMP(how, "kill") == 0 || *how == NUL) | 5051 if (STRCMP(how, "term") == 0 || STRCMP(how, "kill") == 0 || *how == NUL) |
5029 { | 5052 { |
5030 if (job->jv_job_object != NULL) | 5053 return terminate_all(job->jv_proc_info.hProcess, 0) ? OK : FAIL; |
5031 return TerminateJobObject(job->jv_job_object, 0) ? OK : FAIL; | |
5032 else | |
5033 return TerminateProcess(job->jv_proc_info.hProcess, 0) ? OK : FAIL; | |
5034 } | 5054 } |
5035 | 5055 |
5036 if (!AttachConsole(job->jv_proc_info.dwProcessId)) | 5056 if (!AttachConsole(job->jv_proc_info.dwProcessId)) |
5037 return FAIL; | 5057 return FAIL; |
5038 ret = GenerateConsoleCtrlEvent( | 5058 ret = GenerateConsoleCtrlEvent( |
5049 void | 5069 void |
5050 mch_clear_job(job_T *job) | 5070 mch_clear_job(job_T *job) |
5051 { | 5071 { |
5052 if (job->jv_status != JOB_FAILED) | 5072 if (job->jv_status != JOB_FAILED) |
5053 { | 5073 { |
5054 if (job->jv_job_object != NULL) | |
5055 CloseHandle(job->jv_job_object); | |
5056 CloseHandle(job->jv_proc_info.hProcess); | 5074 CloseHandle(job->jv_proc_info.hProcess); |
5057 } | 5075 } |
5058 } | 5076 } |
5059 #endif | 5077 #endif |
5060 | 5078 |