To: vim_dev@googlegroups.com Subject: Patch 7.4.1306 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.1306 Problem: Job control doesn't work well on MS-Windows. Solution: Various fixes. (Ken Takata, Ozaki Kiichi , Yukihiro Nakadaira, Yasuhiro Matsumoto) Files: src/Make_mvc.mak, src/eval.c, src/os_unix.c, src/os_win32.c, src/proto/os_unix.pro, src/proto/os_win32.pro, src/structs.h *** ../vim-7.4.1305/src/Make_mvc.mak 2016-02-02 18:50:41.403602887 +0100 --- src/Make_mvc.mak 2016-02-12 19:18:38.277211213 +0100 *************** *** 113,119 **** # Processor Version: CPUNR=[i386, i486, i586, i686, pentium4] (default is # i386) # ! # Version Support: WINVER=[0x0400, 0x0500] (default is 0x0400) # # Debug version: DEBUG=yes # Mapfile: MAP=[no, yes or lines] (default is yes) --- 113,119 ---- # Processor Version: CPUNR=[i386, i486, i586, i686, pentium4] (default is # i386) # ! # Version Support: WINVER=[0x0400, 0x0500] (default is 0x0500) # # Debug version: DEBUG=yes # Mapfile: MAP=[no, yes or lines] (default is yes) *************** *** 370,378 **** !endif ### Set the default $(WINVER) to make it work with VC++7.0 (VS.NET) - # When set to 0x0500 ":browse" stops working. !ifndef WINVER ! WINVER = 0x0400 !endif # If you have a fixed directory for $VIM or $VIMRUNTIME, other than the normal --- 370,377 ---- !endif ### Set the default $(WINVER) to make it work with VC++7.0 (VS.NET) !ifndef WINVER ! WINVER = 0x0500 !endif # If you have a fixed directory for $VIM or $VIMRUNTIME, other than the normal *** ../vim-7.4.1305/src/eval.c 2016-02-11 21:08:27.540531286 +0100 --- src/eval.c 2016-02-12 19:25:58.172620678 +0100 *************** *** 7720,7727 **** static void job_free(job_T *job) { ! /* TODO: free any handles */ ! vim_free(job); } --- 7720,7726 ---- static void job_free(job_T *job) { ! mch_clear_job(job); vim_free(job); } *************** *** 14369,14377 **** s = vim_strsave_shellescape(s, FALSE, TRUE); if (s == NULL) goto theend; } ! ga_concat(&ga, s); ! vim_free(s); if (li->li_next != NULL) ga_append(&ga, ' '); #endif --- 14368,14378 ---- s = vim_strsave_shellescape(s, FALSE, TRUE); if (s == NULL) goto theend; + ga_concat(&ga, s); + vim_free(s); } ! else ! ga_concat(&ga, s); if (li->li_next != NULL) ga_append(&ga, ' '); #endif *************** *** 21623,21629 **** "process %ld %s", (long)job->jv_pid, status); # elif defined(WIN32) vim_snprintf((char *)buf, NUMBUFLEN, ! "process %ld %s", (long)job->jv_pi.dwProcessId, status); # else /* fall-back */ --- 21624,21631 ---- "process %ld %s", (long)job->jv_pid, status); # elif defined(WIN32) vim_snprintf((char *)buf, NUMBUFLEN, ! "process %ld %s", ! (long)job->jv_proc_info.dwProcessId, status); # else /* fall-back */ *** ../vim-7.4.1305/src/os_unix.c 2016-02-09 11:37:46.417354447 +0100 --- src/os_unix.c 2016-02-12 19:22:31.174780515 +0100 *************** *** 5092,5097 **** --- 5092,5103 ---- job->jv_status = JOB_ENDED; return "dead"; } + if (WIFSIGNALED(status)) + { + job->jv_exitval = -1; + job->jv_status = JOB_ENDED; + return "dead"; + } return "run"; } *************** *** 5099,5104 **** --- 5105,5111 ---- mch_stop_job(job_T *job, char_u *how) { int sig = -1; + pid_t job_pid; if (STRCMP(how, "hup") == 0) sig = SIGHUP; *************** *** 5112,5121 **** sig = atoi((char *)how); else return FAIL; /* TODO: have an option to only kill the process, not the group? */ ! kill(-job->jv_pid, sig); return OK; } #endif /* --- 5119,5148 ---- sig = atoi((char *)how); else return FAIL; + /* TODO: have an option to only kill the process, not the group? */ ! job_pid = job->jv_pid; ! if (job_pid == getpgid(job_pid)) ! job_pid = -job_pid; ! ! kill(job_pid, sig); ! return OK; } + + /* + * Clear the data related to "job". + */ + void + mch_clear_job(job_T *job) + { + /* call waitpid because child process may become zombie */ + # ifdef __NeXT__ + wait4(job->jv_pid, NULL, WNOHANG, (struct rusage *)0); + # else + waitpid(job->jv_pid, NULL, WNOHANG); + # endif + } #endif /* *** ../vim-7.4.1305/src/os_win32.c 2016-02-11 12:48:32.692069619 +0100 --- src/os_win32.c 2016-02-12 19:25:39.000820698 +0100 *************** *** 5038,5056 **** { STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); if (!vim_create_process(cmd, FALSE, CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_PROCESS_GROUP | ! CREATE_NO_WINDOW, &si, &pi)) job->jv_status = JOB_FAILED; else { ! job->jv_pi = pi; job->jv_status = JOB_STARTED; } } --- 5038,5081 ---- { STARTUPINFO si; PROCESS_INFORMATION pi; + HANDLE jo; + jo = CreateJobObject(NULL, NULL); + if (jo == NULL) + { + job->jv_status = JOB_FAILED; + return; + } + + ZeroMemory(&pi, sizeof(pi)); ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); + si.dwFlags = STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; if (!vim_create_process(cmd, FALSE, + CREATE_SUSPENDED | CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_PROCESS_GROUP | ! CREATE_NEW_CONSOLE, &si, &pi)) + { + CloseHandle(jo); job->jv_status = JOB_FAILED; + } else { ! if (!AssignProcessToJobObject(jo, pi.hProcess)) ! { ! /* if failing, switch the way to terminate ! * process with TerminateProcess. */ ! CloseHandle(jo); ! jo = NULL; ! } ! ResumeThread(pi.hThread); ! CloseHandle(job->jv_proc_info.hThread); ! job->jv_proc_info = pi; ! job->jv_job_object = jo; job->jv_status = JOB_STARTED; } } *************** *** 5060,5071 **** { DWORD dwExitCode = 0; ! if (!GetExitCodeProcess(job->jv_pi.hProcess, &dwExitCode)) ! return "dead"; ! if (dwExitCode != STILL_ACTIVE) { ! CloseHandle(job->jv_pi.hProcess); ! CloseHandle(job->jv_pi.hThread); return "dead"; } return "run"; --- 5085,5094 ---- { DWORD dwExitCode = 0; ! if (!GetExitCodeProcess(job->jv_proc_info.hProcess, &dwExitCode) ! || dwExitCode != STILL_ACTIVE) { ! job->jv_status = JOB_ENDED; return "dead"; } return "run"; *************** *** 5074,5087 **** int mch_stop_job(job_T *job, char_u *how) { if (STRCMP(how, "kill") == 0) ! TerminateProcess(job->jv_pi.hProcess, 0); ! else ! return GenerateConsoleCtrlEvent( ! STRCMP(how, "hup") == 0 ? ! CTRL_BREAK_EVENT : CTRL_C_EVENT, ! job->jv_pi.dwProcessId) ? OK : FAIL; ! return OK; } #endif --- 5097,5135 ---- int mch_stop_job(job_T *job, char_u *how) { + int ret = 0; + int ctrl_c = STRCMP(how, "int") == 0; + if (STRCMP(how, "kill") == 0) ! { ! 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; ! } ! ! if (!AttachConsole(job->jv_proc_info.dwProcessId)) ! return FAIL; ! ret = GenerateConsoleCtrlEvent( ! ctrl_c ? CTRL_C_EVENT : CTRL_BREAK_EVENT, ! job->jv_proc_info.dwProcessId) ! ? OK : FAIL; ! FreeConsole(); ! return ret; ! } ! ! /* ! * Clear the data related to "job". ! */ ! void ! 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); ! } } #endif *** ../vim-7.4.1305/src/proto/os_unix.pro 2016-02-07 14:26:12.179054006 +0100 --- src/proto/os_unix.pro 2016-02-12 19:22:35.958730593 +0100 *************** *** 60,65 **** --- 60,66 ---- void mch_start_job(char **argv, job_T *job); char *mch_job_status(job_T *job); int mch_stop_job(job_T *job, char_u *how); + void mch_clear_job(job_T *job); void mch_breakcheck(void); int mch_expandpath(garray_T *gap, char_u *path, int flags); int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***file, int flags); *** ../vim-7.4.1305/src/proto/os_win32.pro 2016-02-07 19:57:12.192788494 +0100 --- src/proto/os_win32.pro 2016-02-12 19:22:41.018677790 +0100 *************** *** 43,48 **** --- 43,49 ---- void mch_start_job(char *cmd, job_T *job); char *mch_job_status(job_T *job); int mch_stop_job(job_T *job, char_u *how); + void mch_clear_job(job_T *job); void mch_set_normal_colors(void); void mch_write(char_u *s, int len); void mch_delay(long msec, int ignoreinput); *** ../vim-7.4.1305/src/structs.h 2016-02-11 12:48:32.696069578 +0100 --- src/structs.h 2016-02-12 19:25:48.324723420 +0100 *************** *** 1249,1255 **** int jv_exitval; #endif #ifdef WIN32 ! PROCESS_INFORMATION jv_pi; #endif jobstatus_T jv_status; --- 1249,1256 ---- int jv_exitval; #endif #ifdef WIN32 ! PROCESS_INFORMATION jv_proc_info; ! HANDLE jv_job_object; #endif jobstatus_T jv_status; *** ../vim-7.4.1305/src/version.c 2016-02-12 19:08:10.479766970 +0100 --- src/version.c 2016-02-12 19:19:57.516384136 +0100 *************** *** 749,750 **** --- 749,752 ---- { /* Add new patch number below this line */ + /**/ + 1306, /**/ -- hundred-and-one symptoms of being an internet addict: 238. You think faxes are old-fashioned. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///