forked from aniani/vim
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)
This commit is contained in:
@@ -113,7 +113,7 @@
|
|||||||
# Processor Version: CPUNR=[i386, i486, i586, i686, pentium4] (default is
|
# Processor Version: CPUNR=[i386, i486, i586, i686, pentium4] (default is
|
||||||
# i386)
|
# i386)
|
||||||
#
|
#
|
||||||
# Version Support: WINVER=[0x0400, 0x0500] (default is 0x0400)
|
# Version Support: WINVER=[0x0400, 0x0500] (default is 0x0500)
|
||||||
#
|
#
|
||||||
# Debug version: DEBUG=yes
|
# Debug version: DEBUG=yes
|
||||||
# Mapfile: MAP=[no, yes or lines] (default is 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
|
!endif
|
||||||
|
|
||||||
### Set the default $(WINVER) to make it work with VC++7.0 (VS.NET)
|
### Set the default $(WINVER) to make it work with VC++7.0 (VS.NET)
|
||||||
# When set to 0x0500 ":browse" stops working.
|
|
||||||
!ifndef WINVER
|
!ifndef WINVER
|
||||||
WINVER = 0x0400
|
WINVER = 0x0500
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
# If you have a fixed directory for $VIM or $VIMRUNTIME, other than the normal
|
# If you have a fixed directory for $VIM or $VIMRUNTIME, other than the normal
|
||||||
|
10
src/eval.c
10
src/eval.c
@@ -7720,8 +7720,7 @@ failret:
|
|||||||
static void
|
static void
|
||||||
job_free(job_T *job)
|
job_free(job_T *job)
|
||||||
{
|
{
|
||||||
/* TODO: free any handles */
|
mch_clear_job(job);
|
||||||
|
|
||||||
vim_free(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);
|
s = vim_strsave_shellescape(s, FALSE, TRUE);
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
|
||||||
ga_concat(&ga, s);
|
ga_concat(&ga, s);
|
||||||
vim_free(s);
|
vim_free(s);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ga_concat(&ga, s);
|
||||||
if (li->li_next != NULL)
|
if (li->li_next != NULL)
|
||||||
ga_append(&ga, ' ');
|
ga_append(&ga, ' ');
|
||||||
#endif
|
#endif
|
||||||
@@ -21623,7 +21624,8 @@ get_tv_string_buf_chk(typval_T *varp, char_u *buf)
|
|||||||
"process %ld %s", (long)job->jv_pid, status);
|
"process %ld %s", (long)job->jv_pid, status);
|
||||||
# elif defined(WIN32)
|
# elif defined(WIN32)
|
||||||
vim_snprintf((char *)buf, NUMBUFLEN,
|
vim_snprintf((char *)buf, NUMBUFLEN,
|
||||||
"process %ld %s", (long)job->jv_pi.dwProcessId,
|
"process %ld %s",
|
||||||
|
(long)job->jv_proc_info.dwProcessId,
|
||||||
status);
|
status);
|
||||||
# else
|
# else
|
||||||
/* fall-back */
|
/* fall-back */
|
||||||
|
@@ -5092,6 +5092,12 @@ mch_job_status(job_T *job)
|
|||||||
job->jv_status = JOB_ENDED;
|
job->jv_status = JOB_ENDED;
|
||||||
return "dead";
|
return "dead";
|
||||||
}
|
}
|
||||||
|
if (WIFSIGNALED(status))
|
||||||
|
{
|
||||||
|
job->jv_exitval = -1;
|
||||||
|
job->jv_status = JOB_ENDED;
|
||||||
|
return "dead";
|
||||||
|
}
|
||||||
return "run";
|
return "run";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5099,6 +5105,7 @@ mch_job_status(job_T *job)
|
|||||||
mch_stop_job(job_T *job, char_u *how)
|
mch_stop_job(job_T *job, char_u *how)
|
||||||
{
|
{
|
||||||
int sig = -1;
|
int sig = -1;
|
||||||
|
pid_t job_pid;
|
||||||
|
|
||||||
if (STRCMP(how, "hup") == 0)
|
if (STRCMP(how, "hup") == 0)
|
||||||
sig = SIGHUP;
|
sig = SIGHUP;
|
||||||
@@ -5112,10 +5119,30 @@ mch_stop_job(job_T *job, char_u *how)
|
|||||||
sig = atoi((char *)how);
|
sig = atoi((char *)how);
|
||||||
else
|
else
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
/* TODO: have an option to only kill the process, not the group? */
|
/* 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;
|
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
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -5038,19 +5038,44 @@ mch_start_job(char *cmd, job_T *job)
|
|||||||
{
|
{
|
||||||
STARTUPINFO si;
|
STARTUPINFO si;
|
||||||
PROCESS_INFORMATION pi;
|
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));
|
ZeroMemory(&si, sizeof(si));
|
||||||
si.cb = sizeof(si);
|
si.cb = sizeof(si);
|
||||||
|
si.dwFlags = STARTF_USESHOWWINDOW;
|
||||||
|
si.wShowWindow = SW_HIDE;
|
||||||
|
|
||||||
if (!vim_create_process(cmd, FALSE,
|
if (!vim_create_process(cmd, FALSE,
|
||||||
|
CREATE_SUSPENDED |
|
||||||
CREATE_DEFAULT_ERROR_MODE |
|
CREATE_DEFAULT_ERROR_MODE |
|
||||||
CREATE_NEW_PROCESS_GROUP |
|
CREATE_NEW_PROCESS_GROUP |
|
||||||
CREATE_NO_WINDOW,
|
CREATE_NEW_CONSOLE,
|
||||||
&si, &pi))
|
&si, &pi))
|
||||||
|
{
|
||||||
|
CloseHandle(jo);
|
||||||
job->jv_status = JOB_FAILED;
|
job->jv_status = JOB_FAILED;
|
||||||
|
}
|
||||||
else
|
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;
|
job->jv_status = JOB_STARTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5060,12 +5085,10 @@ mch_job_status(job_T *job)
|
|||||||
{
|
{
|
||||||
DWORD dwExitCode = 0;
|
DWORD dwExitCode = 0;
|
||||||
|
|
||||||
if (!GetExitCodeProcess(job->jv_pi.hProcess, &dwExitCode))
|
if (!GetExitCodeProcess(job->jv_proc_info.hProcess, &dwExitCode)
|
||||||
return "dead";
|
|| dwExitCode != STILL_ACTIVE)
|
||||||
if (dwExitCode != STILL_ACTIVE)
|
|
||||||
{
|
{
|
||||||
CloseHandle(job->jv_pi.hProcess);
|
job->jv_status = JOB_ENDED;
|
||||||
CloseHandle(job->jv_pi.hThread);
|
|
||||||
return "dead";
|
return "dead";
|
||||||
}
|
}
|
||||||
return "run";
|
return "run";
|
||||||
@@ -5074,14 +5097,39 @@ mch_job_status(job_T *job)
|
|||||||
int
|
int
|
||||||
mch_stop_job(job_T *job, char_u *how)
|
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 (STRCMP(how, "kill") == 0)
|
||||||
TerminateProcess(job->jv_pi.hProcess, 0);
|
{
|
||||||
|
if (job->jv_job_object != NULL)
|
||||||
|
return TerminateJobObject(job->jv_job_object, 0) ? OK : FAIL;
|
||||||
else
|
else
|
||||||
return GenerateConsoleCtrlEvent(
|
return TerminateProcess(job->jv_proc_info.hProcess, 0) ? OK : FAIL;
|
||||||
STRCMP(how, "hup") == 0 ?
|
}
|
||||||
CTRL_BREAK_EVENT : CTRL_C_EVENT,
|
|
||||||
job->jv_pi.dwProcessId) ? OK : FAIL;
|
if (!AttachConsole(job->jv_proc_info.dwProcessId))
|
||||||
return OK;
|
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
|
#endif
|
||||||
|
|
||||||
|
@@ -60,6 +60,7 @@ int mch_call_shell(char_u *cmd, int options);
|
|||||||
void mch_start_job(char **argv, job_T *job);
|
void mch_start_job(char **argv, job_T *job);
|
||||||
char *mch_job_status(job_T *job);
|
char *mch_job_status(job_T *job);
|
||||||
int mch_stop_job(job_T *job, char_u *how);
|
int mch_stop_job(job_T *job, char_u *how);
|
||||||
|
void mch_clear_job(job_T *job);
|
||||||
void mch_breakcheck(void);
|
void mch_breakcheck(void);
|
||||||
int mch_expandpath(garray_T *gap, char_u *path, int flags);
|
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);
|
int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***file, int flags);
|
||||||
|
@@ -43,6 +43,7 @@ int mch_call_shell(char_u *cmd, int options);
|
|||||||
void mch_start_job(char *cmd, job_T *job);
|
void mch_start_job(char *cmd, job_T *job);
|
||||||
char *mch_job_status(job_T *job);
|
char *mch_job_status(job_T *job);
|
||||||
int mch_stop_job(job_T *job, char_u *how);
|
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_set_normal_colors(void);
|
||||||
void mch_write(char_u *s, int len);
|
void mch_write(char_u *s, int len);
|
||||||
void mch_delay(long msec, int ignoreinput);
|
void mch_delay(long msec, int ignoreinput);
|
||||||
|
@@ -1249,7 +1249,8 @@ struct jobvar_S
|
|||||||
int jv_exitval;
|
int jv_exitval;
|
||||||
#endif
|
#endif
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
PROCESS_INFORMATION jv_pi;
|
PROCESS_INFORMATION jv_proc_info;
|
||||||
|
HANDLE jv_job_object;
|
||||||
#endif
|
#endif
|
||||||
jobstatus_T jv_status;
|
jobstatus_T jv_status;
|
||||||
|
|
||||||
|
@@ -747,6 +747,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1306,
|
||||||
/**/
|
/**/
|
||||||
1305,
|
1305,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user