Skip to content

Commit de27989

Browse files
committed
patch 7.4.1536
Problem: Cannot re-use a channel for another job. Solution: Add the "channel" option to job_start().
1 parent 9e49685 commit de27989

8 files changed

Lines changed: 132 additions & 55 deletions

File tree

src/channel.c

Lines changed: 70 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,9 @@ messageFromNetbeans(gpointer clientData,
459459
static void
460460
channel_gui_register_one(channel_T *channel, int part)
461461
{
462+
if (!CH_HAS_GUI)
463+
return;
464+
462465
# ifdef FEAT_GUI_X11
463466
/* Tell notifier we are interested in being called
464467
* when there is input on the editor connection socket. */
@@ -499,12 +502,9 @@ channel_gui_register_one(channel_T *channel, int part)
499502
# endif
500503
}
501504

502-
void
505+
static void
503506
channel_gui_register(channel_T *channel)
504507
{
505-
if (!CH_HAS_GUI)
506-
return;
507-
508508
if (channel->CH_SOCK_FD != INVALID_FD)
509509
channel_gui_register_one(channel, PART_SOCK);
510510
# ifdef CHANNEL_PIPES
@@ -528,6 +528,30 @@ channel_gui_register_all(void)
528528
channel_gui_register(channel);
529529
}
530530

531+
static void
532+
channel_gui_unregister_one(channel_T *channel, int part)
533+
{
534+
# ifdef FEAT_GUI_X11
535+
if (channel->ch_part[part].ch_inputHandler != (XtInputId)NULL)
536+
{
537+
XtRemoveInput(channel->ch_part[part].ch_inputHandler);
538+
channel->ch_part[part].ch_inputHandler = (XtInputId)NULL;
539+
}
540+
# else
541+
# ifdef FEAT_GUI_GTK
542+
if (channel->ch_part[part].ch_inputHandler != 0)
543+
{
544+
# if GTK_CHECK_VERSION(3,0,0)
545+
g_source_remove(channel->ch_part[part].ch_inputHandler);
546+
# else
547+
gdk_input_remove(channel->ch_part[part].ch_inputHandler);
548+
# endif
549+
channel->ch_part[part].ch_inputHandler = 0;
550+
}
551+
# endif
552+
# endif
553+
}
554+
531555
static void
532556
channel_gui_unregister(channel_T *channel)
533557
{
@@ -539,25 +563,7 @@ channel_gui_unregister(channel_T *channel)
539563
part = PART_SOCK;
540564
#endif
541565
{
542-
# ifdef FEAT_GUI_X11
543-
if (channel->ch_part[part].ch_inputHandler != (XtInputId)NULL)
544-
{
545-
XtRemoveInput(channel->ch_part[part].ch_inputHandler);
546-
channel->ch_part[part].ch_inputHandler = (XtInputId)NULL;
547-
}
548-
# else
549-
# ifdef FEAT_GUI_GTK
550-
if (channel->ch_part[part].ch_inputHandler != 0)
551-
{
552-
# if GTK_CHECK_VERSION(3,0,0)
553-
g_source_remove(channel->ch_part[part].ch_inputHandler);
554-
# else
555-
gdk_input_remove(channel->ch_part[part].ch_inputHandler);
556-
# endif
557-
channel->ch_part[part].ch_inputHandler = 0;
558-
}
559-
# endif
560-
# endif
566+
channel_gui_unregister_one(channel, part);
561567
}
562568
}
563569

@@ -830,19 +836,53 @@ channel_open(
830836
channel->ch_nb_close_cb = nb_close_cb;
831837

832838
#ifdef FEAT_GUI
833-
channel_gui_register(channel);
839+
channel_gui_register_one(channel, PART_SOCK);
834840
#endif
835841

836842
return channel;
837843
}
838844

839845
#if defined(CHANNEL_PIPES) || defined(PROTO)
846+
static void
847+
may_close_part(sock_T *fd)
848+
{
849+
if (*fd != INVALID_FD)
850+
{
851+
fd_close(*fd);
852+
*fd = INVALID_FD;
853+
}
854+
}
855+
840856
void
841857
channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err)
842858
{
843-
channel->CH_IN_FD = in;
844-
channel->CH_OUT_FD = out;
845-
channel->CH_ERR_FD = err;
859+
if (in != INVALID_FD)
860+
{
861+
may_close_part(&channel->CH_IN_FD);
862+
channel->CH_IN_FD = in;
863+
}
864+
if (out != INVALID_FD)
865+
{
866+
# if defined(FEAT_GUI)
867+
channel_gui_unregister_one(channel, PART_OUT);
868+
# endif
869+
may_close_part(&channel->CH_OUT_FD);
870+
channel->CH_OUT_FD = out;
871+
# if defined(FEAT_GUI)
872+
channel_gui_register_one(channel, PART_OUT);
873+
# endif
874+
}
875+
if (err != INVALID_FD)
876+
{
877+
# if defined(FEAT_GUI)
878+
channel_gui_unregister_one(channel, PART_ERR);
879+
# endif
880+
may_close_part(&channel->CH_ERR_FD);
881+
channel->CH_ERR_FD = err;
882+
# if defined(FEAT_GUI)
883+
channel_gui_register_one(channel, PART_ERR);
884+
# endif
885+
}
846886
}
847887
#endif
848888

@@ -1912,21 +1952,9 @@ channel_close(channel_T *channel, int invoke_close_cb)
19121952
channel->CH_SOCK_FD = INVALID_FD;
19131953
}
19141954
#if defined(CHANNEL_PIPES)
1915-
if (channel->CH_IN_FD != INVALID_FD)
1916-
{
1917-
fd_close(channel->CH_IN_FD);
1918-
channel->CH_IN_FD = INVALID_FD;
1919-
}
1920-
if (channel->CH_OUT_FD != INVALID_FD)
1921-
{
1922-
fd_close(channel->CH_OUT_FD);
1923-
channel->CH_OUT_FD = INVALID_FD;
1924-
}
1925-
if (channel->CH_ERR_FD != INVALID_FD)
1926-
{
1927-
fd_close(channel->CH_ERR_FD);
1928-
channel->CH_ERR_FD = INVALID_FD;
1929-
}
1955+
may_close_part(&channel->CH_IN_FD);
1956+
may_close_part(&channel->CH_OUT_FD);
1957+
may_close_part(&channel->CH_ERR_FD);
19301958
#endif
19311959

19321960
if (invoke_close_cb && channel->ch_close_cb != NULL)

src/eval.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10164,6 +10164,18 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported)
1016410164
return FAIL;
1016510165
}
1016610166
}
10167+
else if (STRCMP(hi->hi_key, "channel") == 0)
10168+
{
10169+
if (!(supported & JO_OUT_IO))
10170+
break;
10171+
opt->jo_set |= JO_CHANNEL;
10172+
if (item->v_type != VAR_CHANNEL)
10173+
{
10174+
EMSG2(_(e_invarg2), "channel");
10175+
return FAIL;
10176+
}
10177+
opt->jo_channel = item->vval.v_channel;
10178+
}
1016710179
else if (STRCMP(hi->hi_key, "callback") == 0)
1016810180
{
1016910181
if (!(supported & JO_CALLBACK))

src/os_unix.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5111,7 +5111,14 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
51115111

51125112
if (!use_null_for_in || !use_null_for_out || !use_null_for_err)
51135113
{
5114-
channel = add_channel();
5114+
if (options->jo_set & JO_CHANNEL)
5115+
{
5116+
channel = options->jo_channel;
5117+
if (channel != NULL)
5118+
++channel->ch_refcount;
5119+
}
5120+
else
5121+
channel = add_channel();
51155122
if (channel == NULL)
51165123
goto failed;
51175124
}
@@ -5211,7 +5218,7 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
52115218
job->jv_pid = pid;
52125219
job->jv_status = JOB_STARTED;
52135220
# ifdef FEAT_CHANNEL
5214-
job->jv_channel = channel;
5221+
job->jv_channel = channel; /* ch_refcount was set above */
52155222
# endif
52165223

52175224
# ifdef FEAT_CHANNEL
@@ -5232,9 +5239,6 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
52325239
use_out_for_err || use_file_for_err || use_null_for_err
52335240
? INVALID_FD : fd_err[0]);
52345241
channel_set_job(channel, job, options);
5235-
# ifdef FEAT_GUI
5236-
channel_gui_register(channel);
5237-
# endif
52385242
}
52395243
# endif
52405244

@@ -5243,8 +5247,7 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
52435247

52445248
failed: ;
52455249
# ifdef FEAT_CHANNEL
5246-
if (channel != NULL)
5247-
channel_free(channel);
5250+
channel_unref(channel);
52485251
if (fd_in[0] >= 0)
52495252
close(fd_in[0]);
52505253
if (fd_in[1] >= 0)

src/os_win32.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5138,7 +5138,14 @@ mch_start_job(char *cmd, job_T *job, jobopt_T *options)
51385138

51395139
if (!use_null_for_in || !use_null_for_out || !use_null_for_err)
51405140
{
5141-
channel = add_channel();
5141+
if (options->jo_set & JO_CHANNEL)
5142+
{
5143+
channel = options->jo_channel;
5144+
if (channel != NULL)
5145+
++channel->ch_refcount;
5146+
}
5147+
else
5148+
channel = add_channel();
51425149
if (channel == NULL)
51435150
goto failed;
51445151
}
@@ -5188,9 +5195,6 @@ mch_start_job(char *cmd, job_T *job, jobopt_T *options)
51885195
use_out_for_err || use_file_for_err || use_null_for_err
51895196
? INVALID_FD : (sock_T)efd[0]);
51905197
channel_set_job(channel, job, options);
5191-
# ifdef FEAT_GUI
5192-
channel_gui_register(channel);
5193-
# endif
51945198
}
51955199
# endif
51965200
return;
@@ -5203,7 +5207,7 @@ mch_start_job(char *cmd, job_T *job, jobopt_T *options)
52035207
CloseHandle(ifd[1]);
52045208
CloseHandle(ofd[1]);
52055209
CloseHandle(efd[1]);
5206-
channel_free(channel);
5210+
channel_unref(channel);
52075211
# else
52085212
; /* make compiler happy */
52095213
# endif

src/proto/channel.pro

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ void ch_logs(channel_T *ch, char *msg, char *name);
66
channel_T *add_channel(void);
77
int channel_may_free(channel_T *channel);
88
void channel_free(channel_T *channel);
9-
void channel_gui_register(channel_T *channel);
109
void channel_gui_register_all(void);
1110
channel_T *channel_open(char *hostname, int port_in, int waittime, void (*nb_close_cb)(void));
1211
void channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err);

src/structs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,6 +1412,7 @@ struct channel_S {
14121412
#define JO_OUT_BUF 0x1000000 /* "out-buf" */
14131413
#define JO_ERR_BUF 0x2000000 /* "err-buf" (JO_OUT_BUF << 1) */
14141414
#define JO_IN_BUF 0x4000000 /* "in-buf" (JO_OUT_BUF << 2) */
1415+
#define JO_CHANNEL 0x8000000 /* "channel" */
14151416
#define JO_ALL 0xfffffff
14161417

14171418
#define JO_MODE_ALL (JO_MODE + JO_IN_MODE + JO_OUT_MODE + JO_ERR_MODE)
@@ -1443,6 +1444,7 @@ typedef struct
14431444
char_u jo_io_name_buf[4][NUMBUFLEN];
14441445
char_u *jo_io_name[4]; /* not allocated! */
14451446
int jo_io_buf[4];
1447+
channel_T *jo_channel;
14461448

14471449
linenr_T jo_in_top;
14481450
linenr_T jo_in_bot;

src/testdir/test_channel.vim

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,33 @@ func Test_pipe_null()
917917
call job_stop(job)
918918
endfunc
919919

920+
func Test_reuse_channel()
921+
if !has('job')
922+
return
923+
endif
924+
call ch_log('Test_reuse_channel()')
925+
926+
let job = job_start(s:python . " test_channel_pipe.py")
927+
call assert_equal("run", job_status(job))
928+
let handle = job_getchannel(job)
929+
try
930+
call ch_sendraw(handle, "echo something\n")
931+
call assert_equal("something", ch_readraw(handle))
932+
finally
933+
call job_stop(job)
934+
endtry
935+
936+
let job = job_start(s:python . " test_channel_pipe.py", {'channel': handle})
937+
call assert_equal("run", job_status(job))
938+
let handle = job_getchannel(job)
939+
try
940+
call ch_sendraw(handle, "echo again\n")
941+
call assert_equal("again", ch_readraw(handle))
942+
finally
943+
call job_stop(job)
944+
endtry
945+
endfunc
946+
920947
""""""""""
921948

922949
let s:unletResponse = ''

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,8 @@ static char *(features[]) =
743743

744744
static int included_patches[] =
745745
{ /* Add new patch number below this line */
746+
/**/
747+
1536,
746748
/**/
747749
1535,
748750
/**/

0 commit comments

Comments
 (0)