forked from aniani/vim
patch 7.4.1536
Problem: Cannot re-use a channel for another job. Solution: Add the "channel" option to job_start().
This commit is contained in:
112
src/channel.c
112
src/channel.c
@@ -459,6 +459,9 @@ messageFromNetbeans(gpointer clientData,
|
|||||||
static void
|
static void
|
||||||
channel_gui_register_one(channel_T *channel, int part)
|
channel_gui_register_one(channel_T *channel, int part)
|
||||||
{
|
{
|
||||||
|
if (!CH_HAS_GUI)
|
||||||
|
return;
|
||||||
|
|
||||||
# ifdef FEAT_GUI_X11
|
# ifdef FEAT_GUI_X11
|
||||||
/* Tell notifier we are interested in being called
|
/* Tell notifier we are interested in being called
|
||||||
* when there is input on the editor connection socket. */
|
* when there is input on the editor connection socket. */
|
||||||
@@ -499,12 +502,9 @@ channel_gui_register_one(channel_T *channel, int part)
|
|||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
channel_gui_register(channel_T *channel)
|
channel_gui_register(channel_T *channel)
|
||||||
{
|
{
|
||||||
if (!CH_HAS_GUI)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (channel->CH_SOCK_FD != INVALID_FD)
|
if (channel->CH_SOCK_FD != INVALID_FD)
|
||||||
channel_gui_register_one(channel, PART_SOCK);
|
channel_gui_register_one(channel, PART_SOCK);
|
||||||
# ifdef CHANNEL_PIPES
|
# ifdef CHANNEL_PIPES
|
||||||
@@ -528,6 +528,30 @@ channel_gui_register_all(void)
|
|||||||
channel_gui_register(channel);
|
channel_gui_register(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
channel_gui_unregister_one(channel_T *channel, int part)
|
||||||
|
{
|
||||||
|
# ifdef FEAT_GUI_X11
|
||||||
|
if (channel->ch_part[part].ch_inputHandler != (XtInputId)NULL)
|
||||||
|
{
|
||||||
|
XtRemoveInput(channel->ch_part[part].ch_inputHandler);
|
||||||
|
channel->ch_part[part].ch_inputHandler = (XtInputId)NULL;
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
# ifdef FEAT_GUI_GTK
|
||||||
|
if (channel->ch_part[part].ch_inputHandler != 0)
|
||||||
|
{
|
||||||
|
# if GTK_CHECK_VERSION(3,0,0)
|
||||||
|
g_source_remove(channel->ch_part[part].ch_inputHandler);
|
||||||
|
# else
|
||||||
|
gdk_input_remove(channel->ch_part[part].ch_inputHandler);
|
||||||
|
# endif
|
||||||
|
channel->ch_part[part].ch_inputHandler = 0;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
channel_gui_unregister(channel_T *channel)
|
channel_gui_unregister(channel_T *channel)
|
||||||
{
|
{
|
||||||
@@ -539,25 +563,7 @@ channel_gui_unregister(channel_T *channel)
|
|||||||
part = PART_SOCK;
|
part = PART_SOCK;
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
# ifdef FEAT_GUI_X11
|
channel_gui_unregister_one(channel, part);
|
||||||
if (channel->ch_part[part].ch_inputHandler != (XtInputId)NULL)
|
|
||||||
{
|
|
||||||
XtRemoveInput(channel->ch_part[part].ch_inputHandler);
|
|
||||||
channel->ch_part[part].ch_inputHandler = (XtInputId)NULL;
|
|
||||||
}
|
|
||||||
# else
|
|
||||||
# ifdef FEAT_GUI_GTK
|
|
||||||
if (channel->ch_part[part].ch_inputHandler != 0)
|
|
||||||
{
|
|
||||||
# if GTK_CHECK_VERSION(3,0,0)
|
|
||||||
g_source_remove(channel->ch_part[part].ch_inputHandler);
|
|
||||||
# else
|
|
||||||
gdk_input_remove(channel->ch_part[part].ch_inputHandler);
|
|
||||||
# endif
|
|
||||||
channel->ch_part[part].ch_inputHandler = 0;
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -830,19 +836,53 @@ channel_open(
|
|||||||
channel->ch_nb_close_cb = nb_close_cb;
|
channel->ch_nb_close_cb = nb_close_cb;
|
||||||
|
|
||||||
#ifdef FEAT_GUI
|
#ifdef FEAT_GUI
|
||||||
channel_gui_register(channel);
|
channel_gui_register_one(channel, PART_SOCK);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CHANNEL_PIPES) || defined(PROTO)
|
#if defined(CHANNEL_PIPES) || defined(PROTO)
|
||||||
|
static void
|
||||||
|
may_close_part(sock_T *fd)
|
||||||
|
{
|
||||||
|
if (*fd != INVALID_FD)
|
||||||
|
{
|
||||||
|
fd_close(*fd);
|
||||||
|
*fd = INVALID_FD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err)
|
channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err)
|
||||||
{
|
{
|
||||||
channel->CH_IN_FD = in;
|
if (in != INVALID_FD)
|
||||||
channel->CH_OUT_FD = out;
|
{
|
||||||
channel->CH_ERR_FD = err;
|
may_close_part(&channel->CH_IN_FD);
|
||||||
|
channel->CH_IN_FD = in;
|
||||||
|
}
|
||||||
|
if (out != INVALID_FD)
|
||||||
|
{
|
||||||
|
# if defined(FEAT_GUI)
|
||||||
|
channel_gui_unregister_one(channel, PART_OUT);
|
||||||
|
# endif
|
||||||
|
may_close_part(&channel->CH_OUT_FD);
|
||||||
|
channel->CH_OUT_FD = out;
|
||||||
|
# if defined(FEAT_GUI)
|
||||||
|
channel_gui_register_one(channel, PART_OUT);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
if (err != INVALID_FD)
|
||||||
|
{
|
||||||
|
# if defined(FEAT_GUI)
|
||||||
|
channel_gui_unregister_one(channel, PART_ERR);
|
||||||
|
# endif
|
||||||
|
may_close_part(&channel->CH_ERR_FD);
|
||||||
|
channel->CH_ERR_FD = err;
|
||||||
|
# if defined(FEAT_GUI)
|
||||||
|
channel_gui_register_one(channel, PART_ERR);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1912,21 +1952,9 @@ channel_close(channel_T *channel, int invoke_close_cb)
|
|||||||
channel->CH_SOCK_FD = INVALID_FD;
|
channel->CH_SOCK_FD = INVALID_FD;
|
||||||
}
|
}
|
||||||
#if defined(CHANNEL_PIPES)
|
#if defined(CHANNEL_PIPES)
|
||||||
if (channel->CH_IN_FD != INVALID_FD)
|
may_close_part(&channel->CH_IN_FD);
|
||||||
{
|
may_close_part(&channel->CH_OUT_FD);
|
||||||
fd_close(channel->CH_IN_FD);
|
may_close_part(&channel->CH_ERR_FD);
|
||||||
channel->CH_IN_FD = INVALID_FD;
|
|
||||||
}
|
|
||||||
if (channel->CH_OUT_FD != INVALID_FD)
|
|
||||||
{
|
|
||||||
fd_close(channel->CH_OUT_FD);
|
|
||||||
channel->CH_OUT_FD = INVALID_FD;
|
|
||||||
}
|
|
||||||
if (channel->CH_ERR_FD != INVALID_FD)
|
|
||||||
{
|
|
||||||
fd_close(channel->CH_ERR_FD);
|
|
||||||
channel->CH_ERR_FD = INVALID_FD;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (invoke_close_cb && channel->ch_close_cb != NULL)
|
if (invoke_close_cb && channel->ch_close_cb != NULL)
|
||||||
|
12
src/eval.c
12
src/eval.c
@@ -10164,6 +10164,18 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported)
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (STRCMP(hi->hi_key, "channel") == 0)
|
||||||
|
{
|
||||||
|
if (!(supported & JO_OUT_IO))
|
||||||
|
break;
|
||||||
|
opt->jo_set |= JO_CHANNEL;
|
||||||
|
if (item->v_type != VAR_CHANNEL)
|
||||||
|
{
|
||||||
|
EMSG2(_(e_invarg2), "channel");
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
opt->jo_channel = item->vval.v_channel;
|
||||||
|
}
|
||||||
else if (STRCMP(hi->hi_key, "callback") == 0)
|
else if (STRCMP(hi->hi_key, "callback") == 0)
|
||||||
{
|
{
|
||||||
if (!(supported & JO_CALLBACK))
|
if (!(supported & JO_CALLBACK))
|
||||||
|
@@ -5111,7 +5111,14 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
|
|||||||
|
|
||||||
if (!use_null_for_in || !use_null_for_out || !use_null_for_err)
|
if (!use_null_for_in || !use_null_for_out || !use_null_for_err)
|
||||||
{
|
{
|
||||||
channel = add_channel();
|
if (options->jo_set & JO_CHANNEL)
|
||||||
|
{
|
||||||
|
channel = options->jo_channel;
|
||||||
|
if (channel != NULL)
|
||||||
|
++channel->ch_refcount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
channel = add_channel();
|
||||||
if (channel == NULL)
|
if (channel == NULL)
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
@@ -5211,7 +5218,7 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
|
|||||||
job->jv_pid = pid;
|
job->jv_pid = pid;
|
||||||
job->jv_status = JOB_STARTED;
|
job->jv_status = JOB_STARTED;
|
||||||
# ifdef FEAT_CHANNEL
|
# ifdef FEAT_CHANNEL
|
||||||
job->jv_channel = channel;
|
job->jv_channel = channel; /* ch_refcount was set above */
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifdef FEAT_CHANNEL
|
# ifdef FEAT_CHANNEL
|
||||||
@@ -5232,9 +5239,6 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
|
|||||||
use_out_for_err || use_file_for_err || use_null_for_err
|
use_out_for_err || use_file_for_err || use_null_for_err
|
||||||
? INVALID_FD : fd_err[0]);
|
? INVALID_FD : fd_err[0]);
|
||||||
channel_set_job(channel, job, options);
|
channel_set_job(channel, job, options);
|
||||||
# ifdef FEAT_GUI
|
|
||||||
channel_gui_register(channel);
|
|
||||||
# endif
|
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
@@ -5243,8 +5247,7 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
|
|||||||
|
|
||||||
failed: ;
|
failed: ;
|
||||||
# ifdef FEAT_CHANNEL
|
# ifdef FEAT_CHANNEL
|
||||||
if (channel != NULL)
|
channel_unref(channel);
|
||||||
channel_free(channel);
|
|
||||||
if (fd_in[0] >= 0)
|
if (fd_in[0] >= 0)
|
||||||
close(fd_in[0]);
|
close(fd_in[0]);
|
||||||
if (fd_in[1] >= 0)
|
if (fd_in[1] >= 0)
|
||||||
|
@@ -5138,7 +5138,14 @@ mch_start_job(char *cmd, job_T *job, jobopt_T *options)
|
|||||||
|
|
||||||
if (!use_null_for_in || !use_null_for_out || !use_null_for_err)
|
if (!use_null_for_in || !use_null_for_out || !use_null_for_err)
|
||||||
{
|
{
|
||||||
channel = add_channel();
|
if (options->jo_set & JO_CHANNEL)
|
||||||
|
{
|
||||||
|
channel = options->jo_channel;
|
||||||
|
if (channel != NULL)
|
||||||
|
++channel->ch_refcount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
channel = add_channel();
|
||||||
if (channel == NULL)
|
if (channel == NULL)
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
@@ -5188,9 +5195,6 @@ mch_start_job(char *cmd, job_T *job, jobopt_T *options)
|
|||||||
use_out_for_err || use_file_for_err || use_null_for_err
|
use_out_for_err || use_file_for_err || use_null_for_err
|
||||||
? INVALID_FD : (sock_T)efd[0]);
|
? INVALID_FD : (sock_T)efd[0]);
|
||||||
channel_set_job(channel, job, options);
|
channel_set_job(channel, job, options);
|
||||||
# ifdef FEAT_GUI
|
|
||||||
channel_gui_register(channel);
|
|
||||||
# endif
|
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
return;
|
return;
|
||||||
@@ -5203,7 +5207,7 @@ failed:
|
|||||||
CloseHandle(ifd[1]);
|
CloseHandle(ifd[1]);
|
||||||
CloseHandle(ofd[1]);
|
CloseHandle(ofd[1]);
|
||||||
CloseHandle(efd[1]);
|
CloseHandle(efd[1]);
|
||||||
channel_free(channel);
|
channel_unref(channel);
|
||||||
# else
|
# else
|
||||||
; /* make compiler happy */
|
; /* make compiler happy */
|
||||||
# endif
|
# endif
|
||||||
|
@@ -6,7 +6,6 @@ void ch_logs(channel_T *ch, char *msg, char *name);
|
|||||||
channel_T *add_channel(void);
|
channel_T *add_channel(void);
|
||||||
int channel_may_free(channel_T *channel);
|
int channel_may_free(channel_T *channel);
|
||||||
void channel_free(channel_T *channel);
|
void channel_free(channel_T *channel);
|
||||||
void channel_gui_register(channel_T *channel);
|
|
||||||
void channel_gui_register_all(void);
|
void channel_gui_register_all(void);
|
||||||
channel_T *channel_open(char *hostname, int port_in, int waittime, void (*nb_close_cb)(void));
|
channel_T *channel_open(char *hostname, int port_in, int waittime, void (*nb_close_cb)(void));
|
||||||
void channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err);
|
void channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err);
|
||||||
|
@@ -1412,6 +1412,7 @@ struct channel_S {
|
|||||||
#define JO_OUT_BUF 0x1000000 /* "out-buf" */
|
#define JO_OUT_BUF 0x1000000 /* "out-buf" */
|
||||||
#define JO_ERR_BUF 0x2000000 /* "err-buf" (JO_OUT_BUF << 1) */
|
#define JO_ERR_BUF 0x2000000 /* "err-buf" (JO_OUT_BUF << 1) */
|
||||||
#define JO_IN_BUF 0x4000000 /* "in-buf" (JO_OUT_BUF << 2) */
|
#define JO_IN_BUF 0x4000000 /* "in-buf" (JO_OUT_BUF << 2) */
|
||||||
|
#define JO_CHANNEL 0x8000000 /* "channel" */
|
||||||
#define JO_ALL 0xfffffff
|
#define JO_ALL 0xfffffff
|
||||||
|
|
||||||
#define JO_MODE_ALL (JO_MODE + JO_IN_MODE + JO_OUT_MODE + JO_ERR_MODE)
|
#define JO_MODE_ALL (JO_MODE + JO_IN_MODE + JO_OUT_MODE + JO_ERR_MODE)
|
||||||
@@ -1443,6 +1444,7 @@ typedef struct
|
|||||||
char_u jo_io_name_buf[4][NUMBUFLEN];
|
char_u jo_io_name_buf[4][NUMBUFLEN];
|
||||||
char_u *jo_io_name[4]; /* not allocated! */
|
char_u *jo_io_name[4]; /* not allocated! */
|
||||||
int jo_io_buf[4];
|
int jo_io_buf[4];
|
||||||
|
channel_T *jo_channel;
|
||||||
|
|
||||||
linenr_T jo_in_top;
|
linenr_T jo_in_top;
|
||||||
linenr_T jo_in_bot;
|
linenr_T jo_in_bot;
|
||||||
|
@@ -917,6 +917,33 @@ func Test_pipe_null()
|
|||||||
call job_stop(job)
|
call job_stop(job)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_reuse_channel()
|
||||||
|
if !has('job')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
call ch_log('Test_reuse_channel()')
|
||||||
|
|
||||||
|
let job = job_start(s:python . " test_channel_pipe.py")
|
||||||
|
call assert_equal("run", job_status(job))
|
||||||
|
let handle = job_getchannel(job)
|
||||||
|
try
|
||||||
|
call ch_sendraw(handle, "echo something\n")
|
||||||
|
call assert_equal("something", ch_readraw(handle))
|
||||||
|
finally
|
||||||
|
call job_stop(job)
|
||||||
|
endtry
|
||||||
|
|
||||||
|
let job = job_start(s:python . " test_channel_pipe.py", {'channel': handle})
|
||||||
|
call assert_equal("run", job_status(job))
|
||||||
|
let handle = job_getchannel(job)
|
||||||
|
try
|
||||||
|
call ch_sendraw(handle, "echo again\n")
|
||||||
|
call assert_equal("again", ch_readraw(handle))
|
||||||
|
finally
|
||||||
|
call job_stop(job)
|
||||||
|
endtry
|
||||||
|
endfunc
|
||||||
|
|
||||||
""""""""""
|
""""""""""
|
||||||
|
|
||||||
let s:unletResponse = ''
|
let s:unletResponse = ''
|
||||||
|
@@ -743,6 +743,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 */
|
||||||
|
/**/
|
||||||
|
1536,
|
||||||
/**/
|
/**/
|
||||||
1535,
|
1535,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user