]> granicus.if.org Git - vim/commitdiff
patch 7.4.1536 v7.4.1536
authorBram Moolenaar <Bram@vim.org>
Fri, 11 Mar 2016 21:19:44 +0000 (22:19 +0100)
committerBram Moolenaar <Bram@vim.org>
Fri, 11 Mar 2016 21:19:44 +0000 (22:19 +0100)
Problem:    Cannot re-use a channel for another job.
Solution:   Add the "channel" option to job_start().

src/channel.c
src/eval.c
src/os_unix.c
src/os_win32.c
src/proto/channel.pro
src/structs.h
src/testdir/test_channel.vim
src/version.c

index d77a4b7d1bbc3dbeeb6652d0958a27b058c2bae9..f65b31fb14bda7a79bf269833e8d7937eff2b4a7 100644 (file)
@@ -459,6 +459,9 @@ messageFromNetbeans(gpointer clientData,
     static void
 channel_gui_register_one(channel_T *channel, int part)
 {
+    if (!CH_HAS_GUI)
+       return;
+
 # ifdef FEAT_GUI_X11
     /* Tell notifier we are interested in being called
      * when there is input on the editor connection socket. */
@@ -499,12 +502,9 @@ channel_gui_register_one(channel_T *channel, int part)
 # endif
 }
 
-    void
+    static void
 channel_gui_register(channel_T *channel)
 {
-    if (!CH_HAS_GUI)
-       return;
-
     if (channel->CH_SOCK_FD != INVALID_FD)
        channel_gui_register_one(channel, PART_SOCK);
 # ifdef CHANNEL_PIPES
@@ -528,6 +528,30 @@ channel_gui_register_all(void)
        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
 channel_gui_unregister(channel_T *channel)
 {
@@ -539,25 +563,7 @@ channel_gui_unregister(channel_T *channel)
     part = PART_SOCK;
 #endif
     {
-# 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
+       channel_gui_unregister_one(channel, part);
     }
 }
 
@@ -830,19 +836,53 @@ channel_open(
     channel->ch_nb_close_cb = nb_close_cb;
 
 #ifdef FEAT_GUI
-    channel_gui_register(channel);
+    channel_gui_register_one(channel, PART_SOCK);
 #endif
 
     return channel;
 }
 
 #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
 channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err)
 {
-    channel->CH_IN_FD = in;
-    channel->CH_OUT_FD = out;
-    channel->CH_ERR_FD = err;
+    if (in != INVALID_FD)
+    {
+       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
 
@@ -1912,21 +1952,9 @@ channel_close(channel_T *channel, int invoke_close_cb)
        channel->CH_SOCK_FD = INVALID_FD;
     }
 #if defined(CHANNEL_PIPES)
-    if (channel->CH_IN_FD != INVALID_FD)
-    {
-       fd_close(channel->CH_IN_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;
-    }
+    may_close_part(&channel->CH_IN_FD);
+    may_close_part(&channel->CH_OUT_FD);
+    may_close_part(&channel->CH_ERR_FD);
 #endif
 
     if (invoke_close_cb && channel->ch_close_cb != NULL)
index 9f56126f6b9b8cc26810dc45557f62a34273089e..f3ebaa5e05a0463b59fc55f1f81a27bec4e0ba9b 100644 (file)
@@ -10164,6 +10164,18 @@ get_job_options(typval_T *tv, jobopt_T *opt, int supported)
                    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)
            {
                if (!(supported & JO_CALLBACK))
index 7eb4e710c9aa1dcfb16b502e0a3bc2b1e3820976..8a611666fcc4629bd7c55b09a2d9ee94a95b118b 100644 (file)
@@ -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)
     {
-       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)
            goto failed;
     }
@@ -5211,7 +5218,7 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
     job->jv_pid = pid;
     job->jv_status = JOB_STARTED;
 # ifdef FEAT_CHANNEL
-    job->jv_channel = channel;
+    job->jv_channel = channel;  /* ch_refcount was set above */
 # endif
 
 # 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
                                                    ? INVALID_FD : fd_err[0]);
        channel_set_job(channel, job, options);
-#  ifdef FEAT_GUI
-       channel_gui_register(channel);
-#  endif
     }
 # endif
 
@@ -5243,8 +5247,7 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
 
 failed: ;
 # ifdef FEAT_CHANNEL
-    if (channel != NULL)
-       channel_free(channel);
+    channel_unref(channel);
     if (fd_in[0] >= 0)
        close(fd_in[0]);
     if (fd_in[1] >= 0)
index c4dc349a3b0e352dcdbcd2c497b2808acb3d9835..49fd0f703159aeaff81919bbb565a7240bd6a334 100644 (file)
@@ -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)
     {
-       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)
            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
                                            ? INVALID_FD : (sock_T)efd[0]);
        channel_set_job(channel, job, options);
-#  ifdef FEAT_GUI
-       channel_gui_register(channel);
-#  endif
     }
 # endif
     return;
@@ -5203,7 +5207,7 @@ failed:
     CloseHandle(ifd[1]);
     CloseHandle(ofd[1]);
     CloseHandle(efd[1]);
-    channel_free(channel);
+    channel_unref(channel);
 # else
     ;  /* make compiler happy */
 # endif
index 18dceb521abdf185072d4c6d6f9eb2985493c7dc..bb7bab31c00a9e36d684bc73d34fe9ca33de26cb 100644 (file)
@@ -6,7 +6,6 @@ void ch_logs(channel_T *ch, char *msg, char *name);
 channel_T *add_channel(void);
 int channel_may_free(channel_T *channel);
 void channel_free(channel_T *channel);
-void channel_gui_register(channel_T *channel);
 void channel_gui_register_all(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);
index 373405ce0ebad307134879d81fc3f63ef192891a..9ccc09a12154a2960abe60eb7311a16929aaaa61 100644 (file)
@@ -1412,6 +1412,7 @@ struct channel_S {
 #define JO_OUT_BUF         0x1000000   /* "out-buf" */
 #define JO_ERR_BUF         0x2000000   /* "err-buf" (JO_OUT_BUF << 1) */
 #define JO_IN_BUF          0x4000000   /* "in-buf" (JO_OUT_BUF << 2) */
+#define JO_CHANNEL         0x8000000   /* "channel" */
 #define JO_ALL             0xfffffff
 
 #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[4]; /* not allocated! */
     int                jo_io_buf[4];
+    channel_T  *jo_channel;
 
     linenr_T   jo_in_top;
     linenr_T   jo_in_bot;
index 909afea8a35bba3e33411d8708f432dfe399fd19..5f2b97f70fe4df723e0e0b199885618f5ee0fadb 100644 (file)
@@ -917,6 +917,33 @@ func Test_pipe_null()
   call job_stop(job)
 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 = ''
index d138eb844e042391e8afa10a898af621d3f05e54..4f6c51d60f53c60c1cdc1b9dd0b02d58af0cc72b 100644 (file)
@@ -743,6 +743,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1536,
 /**/
     1535,
 /**/