]> granicus.if.org Git - vim/commitdiff
patch 7.4.1306 v7.4.1306
authorBram Moolenaar <Bram@vim.org>
Fri, 12 Feb 2016 18:30:26 +0000 (19:30 +0100)
committerBram Moolenaar <Bram@vim.org>
Fri, 12 Feb 2016 18:30:26 +0000 (19:30 +0100)
Problem:    Job control doesn't work well on MS-Windows.
Solution:   Various fixes. (Ken Takata, Ozaki Kiichi , Yukihiro Nakadaira,
            Yasuhiro Matsumoto)

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
src/version.c

index 11d562959c2e5b5b2f808f82fa7efb75acc04c7a..6cada65607360dffd630c7b8ec8af8c718fe4d79 100644 (file)
 #      Processor Version: CPUNR=[i386, i486, i586, i686, pentium4] (default is
 #      i386)
 #
-#      Version Support: WINVER=[0x0400, 0x0500] (default is 0x0400)
+#      Version Support: WINVER=[0x0400, 0x0500] (default is 0x0500)
 #
 #      Debug version: DEBUG=yes
 #      Mapfile: MAP=[no, yes or lines] (default is yes)
@@ -370,9 +370,8 @@ CON_LIB = $(CON_LIB) /DELAYLOAD:comdlg32.dll /DELAYLOAD:ole32.dll DelayImp.lib
 !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
+WINVER = 0x0500
 !endif
 
 # If you have a fixed directory for $VIM or $VIMRUNTIME, other than the normal
index 30d5684bf3a6c7e46a834a4e1ad1f0effd759563..ece87def444b83e1f8ec0d6c7ca090da1247f29e 100644 (file)
@@ -7720,8 +7720,7 @@ failret:
     static void
 job_free(job_T *job)
 {
-    /* TODO: free any handles */
-
+    mch_clear_job(job);
     vim_free(job);
 }
 
@@ -14369,9 +14368,11 @@ f_job_start(typval_T *argvars UNUSED, typval_T *rettv)
                s = vim_strsave_shellescape(s, FALSE, TRUE);
                if (s == NULL)
                    goto theend;
+               ga_concat(&ga, s);
+               vim_free(s);
            }
-           ga_concat(&ga, s);
-           vim_free(s);
+           else
+               ga_concat(&ga, s);
            if (li->li_next != NULL)
                ga_append(&ga, ' ');
 #endif
@@ -21623,7 +21624,8 @@ get_tv_string_buf_chk(typval_T *varp, char_u *buf)
                            "process %ld %s", (long)job->jv_pid, status);
 # elif defined(WIN32)
                vim_snprintf((char *)buf, NUMBUFLEN,
-                           "process %ld %s", (long)job->jv_pi.dwProcessId,
+                           "process %ld %s",
+                           (long)job->jv_proc_info.dwProcessId,
                            status);
 # else
                /* fall-back */
index 17bb32268d7bf86d6b12df08916fd0cea47d968a..83ae75f79815ae30912dded548fedb08cad69415 100644 (file)
@@ -5092,6 +5092,12 @@ mch_job_status(job_T *job)
        job->jv_status = JOB_ENDED;
        return "dead";
     }
+    if (WIFSIGNALED(status))
+    {
+       job->jv_exitval = -1;
+       job->jv_status = JOB_ENDED;
+       return "dead";
+    }
     return "run";
 }
 
@@ -5099,6 +5105,7 @@ mch_job_status(job_T *job)
 mch_stop_job(job_T *job, char_u *how)
 {
     int sig = -1;
+    pid_t job_pid;
 
     if (STRCMP(how, "hup") == 0)
        sig = SIGHUP;
@@ -5112,10 +5119,30 @@ mch_stop_job(job_T *job, char_u *how)
        sig = atoi((char *)how);
     else
        return FAIL;
+
     /* TODO: have an option to only kill the process, not the group? */
-    kill(-job->jv_pid, sig);
+    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
 
 /*
index 5841d135d02bbd51ccbe65c1d0e0bfd96894f03e..cc5fc3dee9813be594d112d9743c0def1a5392dd 100644 (file)
@@ -5038,19 +5038,44 @@ mch_start_job(char *cmd, job_T *job)
 {
     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_NO_WINDOW,
+           CREATE_NEW_CONSOLE,
            &si, &pi))
+    {
+       CloseHandle(jo);
        job->jv_status = JOB_FAILED;
+    }
     else
     {
-       job->jv_pi = pi;
+       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,12 +5085,10 @@ mch_job_status(job_T *job)
 {
     DWORD dwExitCode = 0;
 
-    if (!GetExitCodeProcess(job->jv_pi.hProcess, &dwExitCode))
-       return "dead";
-    if (dwExitCode != STILL_ACTIVE)
+    if (!GetExitCodeProcess(job->jv_proc_info.hProcess, &dwExitCode)
+           || dwExitCode != STILL_ACTIVE)
     {
-       CloseHandle(job->jv_pi.hProcess);
-       CloseHandle(job->jv_pi.hThread);
+       job->jv_status = JOB_ENDED;
        return "dead";
     }
     return "run";
@@ -5074,14 +5097,39 @@ mch_job_status(job_T *job)
     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)
-       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;
+    {
+       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
 
index bc250c87eb9f76461bb300a69aef68e937d5977c..c97f7fecf956581f9c197ac32eb4bbd34cebc3a6 100644 (file)
@@ -60,6 +60,7 @@ int mch_call_shell(char_u *cmd, int options);
 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);
index 2128807ce59b17c5587e4aa563f689b1f0082132..2fa6e10246210d7f9bb543b1eab0c6032934c867 100644 (file)
@@ -43,6 +43,7 @@ int mch_call_shell(char_u *cmd, int options);
 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);
index 1ce98d025242ac65f056547c5e9b469a9dbee31e..8ea43d3076d9636a937d9c3fab3859b4b8ec7e85 100644 (file)
@@ -1249,7 +1249,8 @@ struct jobvar_S
     int                jv_exitval;
 #endif
 #ifdef WIN32
-    PROCESS_INFORMATION        jv_pi;
+    PROCESS_INFORMATION        jv_proc_info;
+    HANDLE             jv_job_object;
 #endif
     jobstatus_T        jv_status;
 
index b73ad024c797006368038fcc01a5e5232add972f..7a99caa10e9667e82b86077872b4828520cf8999 100644 (file)
@@ -747,6 +747,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1306,
 /**/
     1305,
 /**/