]> granicus.if.org Git - vim/commitdiff
patch 7.4.1318 v7.4.1318
authorBram Moolenaar <Bram@vim.org>
Sun, 14 Feb 2016 18:13:43 +0000 (19:13 +0100)
committerBram Moolenaar <Bram@vim.org>
Sun, 14 Feb 2016 18:13:43 +0000 (19:13 +0100)
Problem:    Channel with pipes doesn't work in GUI.
Solution:   Register input handlers for pipes.

src/channel.c
src/eval.c
src/feature.h
src/gui_w48.c
src/os_unix.c
src/os_win32.c
src/proto/channel.pro
src/structs.h
src/version.c

index dc05587be532a1932b5ff40058360f5e12e8e89e..daf1c34caf6efe9a315e6b4f525f88dd1ad91b10 100644 (file)
@@ -213,7 +213,8 @@ static int next_ch_id = 0;
     channel_T *
 add_channel(void)
 {
-    channel_T *channel = (channel_T *)alloc_clear((int)sizeof(channel_T));
+    int                which;
+    channel_T  *channel = (channel_T *)alloc_clear((int)sizeof(channel_T));
 
     if (channel == NULL)
        return NULL;
@@ -221,21 +222,23 @@ add_channel(void)
     channel->ch_id = next_ch_id++;
     ch_log(channel, "Opening channel\n");
 
-    channel->ch_sock = (sock_T)-1;
 #ifdef CHANNEL_PIPES
-    channel->ch_in = -1;
-    channel->ch_out = -1;
-    channel->ch_err = -1;
+    for (which = CHAN_SOCK; which <= CHAN_IN; ++which)
+#else
+    which = CHAN_SOCK;
 #endif
+    {
+       channel->ch_pfd[which].ch_fd = (sock_T)-1;
 #ifdef FEAT_GUI_X11
-    channel->ch_inputHandler = (XtInputId)NULL;
+       channel->ch_pfd[which].ch_inputHandler = (XtInputId)NULL;
 #endif
 #ifdef FEAT_GUI_GTK
-    channel->ch_inputHandler = 0;
+       channel->ch_pfd[which].ch_inputHandler = 0;
 #endif
 #ifdef FEAT_GUI_W32
-    channel->ch_inputHandler = -1;
+       channel->ch_pfd[which].ch_inputHandler = -1;
 #endif
+    }
 
     channel->ch_timeout = 2000;
 
@@ -290,7 +293,7 @@ channel_read_netbeans(int id)
     if (channel == NULL)
        ch_errorn(NULL, "Channel %d not found", id);
     else
-       channel_read(channel, FALSE, "messageFromNetbeans");
+       channel_read(channel, -1, "messageFromNetbeans");
 }
 #endif
 
@@ -318,44 +321,55 @@ messageFromNetbeans(gpointer clientData,
 #endif
 
     static void
-channel_gui_register(channel_T *channel)
+channel_gui_register_one(channel_T *channel, int which)
 {
-    if (!CH_HAS_GUI)
-       return;
-
-    /* TODO: pipes */
 # ifdef FEAT_GUI_X11
-    /* tell notifier we are interested in being called
-     * when there is input on the editor connection socket
-     */
-    if (channel->ch_inputHandler == (XtInputId)NULL)
-       channel->ch_inputHandler =
-           XtAppAddInput((XtAppContext)app_context, channel->ch_sock,
-                        (XtPointer)(XtInputReadMask + XtInputExceptMask),
-                       messageFromNetbeans, (XtPointer)(long)channel->ch_id);
+    /* Tell notifier we are interested in being called
+     * when there is input on the editor connection socket. */
+    if (channel->ch_pfd[which].ch_inputHandler == (XtInputId)NULL)
+       channel->ch_pfd[which].ch_inputHandler = XtAppAddInput(
+               (XtAppContext)app_context,
+               channel->ch_pfd[which].ch_fd,
+               (XtPointer)(XtInputReadMask + XtInputExceptMask),
+               messageFromNetbeans,
+               (XtPointer)(long)channel->ch_id);
 # else
 #  ifdef FEAT_GUI_GTK
-    /*
-     * Tell gdk we are interested in being called when there
-     * is input on the editor connection socket
-     */
-    if (channel->ch_inputHandler == 0)
-       channel->ch_inputHandler =
-           gdk_input_add((gint)channel->ch_sock, (GdkInputCondition)
-                            ((int)GDK_INPUT_READ + (int)GDK_INPUT_EXCEPTION),
-                        messageFromNetbeans, (gpointer)(long)channel->ch_id);
+    /* Tell gdk we are interested in being called when there
+     * is input on the editor connection socket. */
+    if (channel->ch_pfd[which].ch_inputHandler == 0)
+       channel->ch_pfd[which].ch_inputHandler = gdk_input_add(
+               (gint)channel->ch_pfd[which].ch_fd, (GdkInputCondition)
+               ((int)GDK_INPUT_READ + (int)GDK_INPUT_EXCEPTION),
+               messageFromNetbeans,
+               (gpointer)(long)channel->ch_id);
 #  else
 #   ifdef FEAT_GUI_W32
-    /*
-     * Tell Windows we are interested in receiving message when there
-     * is input on the editor connection socket.
-     */
-    if (channel->ch_inputHandler == -1)
-       channel->ch_inputHandler =
-           WSAAsyncSelect(channel->ch_sock, s_hwnd, WM_NETBEANS, FD_READ);
+    /* Tell Windows we are interested in receiving message when there
+     * is input on the editor connection socket.  */
+    if (channel->ch_pfd[which].ch_inputHandler == -1)
+       channel->ch_pfd[which].ch_inputHandler = WSAAsyncSelect(
+               channel->ch_pfd[which].ch_fd,
+               s_hwnd, WM_NETBEANS, FD_READ);
 #   endif
 #  endif
 # endif
+}
+
+    void
+channel_gui_register(channel_T *channel)
+{
+    if (!CH_HAS_GUI)
+       return;
+
+    if (channel->ch_pfd[CHAN_SOCK].ch_fd >= 0)
+       channel_gui_register_one(channel, CHAN_SOCK);
+# ifdef CHANNEL_PIPES
+    if (channel->ch_pfd[CHAN_OUT].ch_fd >= 0)
+       channel_gui_register_one(channel, CHAN_OUT);
+    if (channel->ch_pfd[CHAN_ERR].ch_fd >= 0)
+       channel_gui_register_one(channel, CHAN_ERR);
+# endif
 }
 
 /*
@@ -368,38 +382,48 @@ channel_gui_register_all(void)
     channel_T *channel;
 
     for (channel = first_channel; channel != NULL; channel = channel->ch_next)
-       /* TODO: pipes */
-       if (channel->ch_sock >= 0)
-           channel_gui_register(channel);
+       channel_gui_register(channel);
 }
 
     static void
-channel_gui_unregister(channel_T *channel)
+channel_gui_unregister_one(channel_T *channel, int which)
 {
-    /* TODO: pipes */
 # ifdef FEAT_GUI_X11
-    if (channel->ch_inputHandler != (XtInputId)NULL)
+    if (channel->ch_pfd[which].ch_inputHandler != (XtInputId)NULL)
     {
-       XtRemoveInput(channel->ch_inputHandler);
-       channel->ch_inputHandler = (XtInputId)NULL;
+       XtRemoveInput(channel->ch_pfd[which].ch_inputHandler);
+       channel->ch_pfd[which].ch_inputHandler = (XtInputId)NULL;
     }
 # else
 #  ifdef FEAT_GUI_GTK
-    if (channel->ch_inputHandler != 0)
+    if (channel->ch_pfd[which].ch_inputHandler != 0)
     {
-       gdk_input_remove(channel->ch_inputHandler);
-       channel->ch_inputHandler = 0;
+       gdk_input_remove(channel->ch_pfd[which].ch_inputHandler);
+       channel->ch_pfd[which].ch_inputHandler = 0;
     }
 #  else
 #   ifdef FEAT_GUI_W32
-    if (channel->ch_inputHandler == 0)
+    if (channel->ch_pfd[which].ch_inputHandler == 0)
     {
-       WSAAsyncSelect(channel->ch_sock, s_hwnd, 0, 0);
-       channel->ch_inputHandler = -1;
+       WSAAsyncSelect(channel->ch_pfd[which].ch_fd, s_hwnd, 0, 0);
+       channel->ch_pfd[which].ch_inputHandler = -1;
     }
 #   endif
 #  endif
 # endif
+}
+
+    static void
+channel_gui_unregister(channel_T *channel)
+{
+    if (channel->ch_pfd[CHAN_SOCK].ch_fd >= 0)
+       channel_gui_unregister_one(channel, CHAN_SOCK);
+# ifdef CHANNEL_PIPES
+    if (channel->ch_pfd[CHAN_OUT].ch_fd >= 0)
+       channel_gui_unregister_one(channel, CHAN_OUT);
+    if (channel->ch_pfd[CHAN_ERR].ch_fd >= 0)
+       channel_gui_unregister_one(channel, CHAN_ERR);
+# endif
 }
 
 #endif
@@ -440,6 +464,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
     {
        ch_error(NULL, "in socket() in channel_open().\n");
        PERROR("E898: socket() in channel_open()");
+       channel_free(channel);
        return NULL;
     }
 
@@ -453,6 +478,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
        ch_error(NULL, "in gethostbyname() in channel_open()\n");
        PERROR("E901: gethostbyname() in channel_open()");
        sock_close(sd);
+       channel_free(channel);
        return NULL;
     }
     memcpy((char *)&server.sin_addr, host->h_addr, host->h_length);
@@ -472,6 +498,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
            ch_errorn(NULL, "channel_open: Connect failed with errno %d\n",
                                                                       errno);
            sock_close(sd);
+           channel_free(channel);
            return NULL;
        }
     }
@@ -492,6 +519,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
                                                                       errno);
            PERROR(_("E902: Cannot connect to port"));
            sock_close(sd);
+           channel_free(channel);
            return NULL;
        }
     }
@@ -513,12 +541,14 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
                                                                       errno);
            PERROR(_("E902: Cannot connect to port"));
            sock_close(sd);
+           channel_free(channel);
            return NULL;
        }
        if (!FD_ISSET(sd, &wfds))
        {
            /* don't give an error, we just timed out. */
            sock_close(sd);
+           channel_free(channel);
            return NULL;
        }
     }
@@ -542,6 +572,7 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
            SOCK_ERRNO;
            ch_log(NULL, "socket() retry in channel_open()\n");
            PERROR("E900: socket() retry in channel_open()");
+           channel_free(channel);
            return NULL;
        }
        if (connect(sd, (struct sockaddr *)&server, sizeof(server)))
@@ -575,12 +606,13 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
                ch_error(NULL, "Cannot connect to port after retry\n");
                PERROR(_("E899: Cannot connect to port after retry2"));
                sock_close(sd);
+               channel_free(channel);
                return NULL;
            }
        }
     }
 
-    channel->ch_sock = sd;
+    channel->CH_SOCK = sd;
     channel->ch_close_cb = close_cb;
 
 #ifdef FEAT_GUI
@@ -594,9 +626,9 @@ channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
     void
 channel_set_pipes(channel_T *channel, int in, int out, int err)
 {
-    channel->ch_in = in;
-    channel->ch_out = out;
-    channel->ch_err = err;
+    channel->CH_IN = in;
+    channel->CH_OUT = out;
+    channel->CH_ERR = err;
 }
 #endif
 
@@ -1115,9 +1147,9 @@ may_invoke_callback(channel_T *channel)
     int
 channel_can_write_to(channel_T *channel)
 {
-    return channel != NULL && (channel->ch_sock >= 0
+    return channel != NULL && (channel->CH_SOCK >= 0
 #ifdef CHANNEL_PIPES
-                         || channel->ch_in >= 0
+                         || channel->CH_IN >= 0
 #endif
                          );
 }
@@ -1129,11 +1161,11 @@ channel_can_write_to(channel_T *channel)
     int
 channel_is_open(channel_T *channel)
 {
-    return channel != NULL && (channel->ch_sock >= 0
+    return channel != NULL && (channel->CH_SOCK >= 0
 #ifdef CHANNEL_PIPES
-                         || channel->ch_in >= 0
-                         || channel->ch_out >= 0
-                         || channel->ch_err >= 0
+                         || channel->CH_IN >= 0
+                         || channel->CH_OUT >= 0
+                         || channel->CH_ERR >= 0
 #endif
                          );
 }
@@ -1160,10 +1192,10 @@ channel_close(channel_T *channel)
 {
     ch_log(channel, "Closing channel");
 
-    if (channel->ch_sock >= 0)
+    if (channel->CH_SOCK >= 0)
     {
-       sock_close(channel->ch_sock);
-       channel->ch_sock = -1;
+       sock_close(channel->CH_SOCK);
+       channel->CH_SOCK = -1;
        channel->ch_close_cb = NULL;
 #ifdef FEAT_GUI
        channel_gui_unregister(channel);
@@ -1172,20 +1204,20 @@ channel_close(channel_T *channel)
        channel->ch_callback = NULL;
     }
 #if defined(CHANNEL_PIPES)
-    if (channel->ch_in >= 0)
+    if (channel->CH_IN >= 0)
     {
-       close(channel->ch_in);
-       channel->ch_in = -1;
+       close(channel->CH_IN);
+       channel->CH_IN = -1;
     }
-    if (channel->ch_out >= 0)
+    if (channel->CH_OUT >= 0)
     {
-       close(channel->ch_out);
-       channel->ch_out = -1;
+       close(channel->CH_OUT);
+       channel->CH_OUT = -1;
     }
-    if (channel->ch_err >= 0)
+    if (channel->CH_ERR >= 0)
     {
-       close(channel->ch_err);
-       channel->ch_err = -1;
+       close(channel->CH_ERR);
+       channel->CH_ERR = -1;
     }
 #endif
     channel_clear(channel);
@@ -1351,17 +1383,16 @@ channel_get_id(void)
 
 /*
  * Get the file descriptor to read from, either the socket or stdout.
+ * TODO: never gets stderr.
  */
     static int
-get_read_fd(channel_T *channel, int use_stderr)
+get_read_fd(channel_T *channel)
 {
-    if (channel->ch_sock >= 0)
-       return channel->ch_sock;
+    if (channel->CH_SOCK >= 0)
+       return channel->CH_SOCK;
 #if defined(CHANNEL_PIPES)
-    if (!use_stderr && channel->ch_out >= 0)
-       return channel->ch_out;
-    if (use_stderr && channel->ch_err >= 0)
-       return channel->ch_err;
+    if (channel->CH_OUT >= 0)
+       return channel->CH_OUT;
 #endif
     ch_error(channel, "channel_read() called while socket is closed\n");
     return -1;
@@ -1369,10 +1400,11 @@ get_read_fd(channel_T *channel, int use_stderr)
 
 /*
  * Read from channel "channel" for as long as there is something to read.
+ * "which" is CHAN_SOCK, CHAN_OUT or CHAN_ERR.  When -1 guess.
  * The data is put in the read queue.
  */
     void
-channel_read(channel_T *channel, int use_stderr, char *func)
+channel_read(channel_T *channel, int which, char *func)
 {
     static char_u      *buf = NULL;
     int                        len = 0;
@@ -1380,10 +1412,13 @@ channel_read(channel_T *channel, int use_stderr, char *func)
     int                        fd;
     int                        use_socket = FALSE;
 
-    fd = get_read_fd(channel, use_stderr);
+    if (which < 0)
+       fd = get_read_fd(channel);
+    else
+       fd = channel->ch_pfd[which].ch_fd;
     if (fd < 0)
        return;
-    use_socket = channel->ch_sock >= 0;
+    use_socket = fd == channel->CH_SOCK;
 
     /* Allocate a buffer to read into. */
     if (buf == NULL)
@@ -1450,7 +1485,7 @@ channel_read(channel_T *channel, int use_stderr, char *func)
        else
        {
            close(fd);
-           channel->ch_out = -1;
+           channel->CH_OUT = -1;
        }
 #endif
 
@@ -1480,13 +1515,14 @@ channel_read_block(channel_T *channel)
     ch_log(channel, "Reading raw\n");
     if (channel_peek(channel) == NULL)
     {
-       int fd = get_read_fd(channel, FALSE);
+       int fd = get_read_fd(channel);
 
+       /* TODO: read both out and err if they are different */
        ch_log(channel, "No readahead\n");
        /* Wait for up to the channel timeout. */
        if (fd < 0 || channel_wait(channel, fd, channel->ch_timeout) == FAIL)
            return NULL;
-       channel_read(channel, FALSE, "channel_read_block");
+       channel_read(channel, -1, "channel_read_block");
     }
 
     /* TODO: only get the first message */
@@ -1526,11 +1562,11 @@ channel_read_json_block(channel_T *channel, int id, typval_T **rettv)
                continue;
 
            /* Wait for up to the channel timeout. */
-           fd = get_read_fd(channel, FALSE);
+           fd = get_read_fd(channel);
            if (fd < 0 || channel_wait(channel, fd, channel->ch_timeout)
                                                                      == FAIL)
                break;
-           channel_read(channel, FALSE, "channel_read_json_block");
+           channel_read(channel, -1, "channel_read_json_block");
        }
     }
     channel->ch_block_id = 0;
@@ -1539,24 +1575,28 @@ channel_read_json_block(channel_T *channel, int id, typval_T **rettv)
 
 # if defined(WIN32) || defined(PROTO)
 /*
- * Lookup the channel from the socket.
+ * Lookup the channel from the socket.  Set "which" to the fd index.
  * Returns NULL when the socket isn't found.
  */
     channel_T *
-channel_fd2channel(sock_T fd)
+channel_fd2channel(sock_T fd, int *whichp)
 {
-    channel_T *channel;
+    channel_T  *channel;
+    int                i;
 
     if (fd >= 0)
        for (channel = first_channel; channel != NULL;
                                                   channel = channel->ch_next)
-           if (channel->ch_sock == fd
-#  if defined(CHANNEL_PIPES)
-                   || channel->ch_out == fd
-                   || channel->ch_err == fd
+#  ifdef CHANNEL_PIPES
+           for (i = CHAN_SOCK; i < CHAN_IN; ++i)
+#  else
+           i = CHAN_SOCK;
 #  endif
-                   )
-               return channel;
+               if (channel->ch_pfd[i].ch_fd == fd)
+               {
+                   *whichp = i;
+                   return channel
+               }
     return NULL;
 }
 # endif
@@ -1574,14 +1614,14 @@ channel_send(channel_T *channel, char_u *buf, char *fun)
     int                fd = -1;
     int                use_socket = FALSE;
 
-    if (channel->ch_sock >= 0)
+    if (channel->CH_SOCK >= 0)
     {
-       fd = channel->ch_sock;
+       fd = channel->CH_SOCK;
        use_socket = TRUE;
     }
 #if defined(CHANNEL_PIPES)
-    else if (channel->ch_in >= 0)
-       fd = channel->ch_in;
+    else if (channel->CH_IN >= 0)
+       fd = channel->CH_IN;
 #endif
     if (fd < 0)
     {
@@ -1631,44 +1671,26 @@ channel_send(channel_T *channel, char_u *buf, char *fun)
     int
 channel_poll_setup(int nfd_in, void *fds_in)
 {
-    int nfd = nfd_in;
-    channel_T *channel;
-    struct pollfd *fds = fds_in;
+    int                nfd = nfd_in;
+    channel_T  *channel;
+    struct     pollfd *fds = fds_in;
+    int                which;
 
     for (channel = first_channel; channel != NULL; channel = channel->ch_next)
-    {
-       if (channel->ch_sock >= 0)
-       {
-           channel->ch_sock_idx = nfd;
-           fds[nfd].fd = channel->ch_sock;
-           fds[nfd].events = POLLIN;
-           nfd++;
-       }
-       else
-           channel->ch_sock_idx = -1;
-
 #  ifdef CHANNEL_PIPES
-       if (channel->ch_out >= 0)
-       {
-           channel->ch_out_idx = nfd;
-           fds[nfd].fd = channel->ch_out;
-           fds[nfd].events = POLLIN;
-           nfd++;
-       }
-       else
-           channel->ch_out_idx = -1;
-
-       if (channel->ch_err >= 0)
-       {
-           channel->ch_err_idx = nfd;
-           fds[nfd].fd = channel->ch_err;
-           fds[nfd].events = POLLIN;
-           nfd++;
-       }
-       else
-           channel->ch_err_idx = -1;
+       for (which = CHAN_SOCK; which < CHAN_IN; ++which)
+#  else
+       which = CHAN_SOCK;
 #  endif
-    }
+           if (channel->ch_pfd[which].ch_fd >= 0)
+           {
+               channel->ch_pfd[which].ch_poll_idx = nfd;
+               fds[nfd].fd = channel->ch_pfd[which].ch_fd;
+               fds[nfd].events = POLLIN;
+               nfd++;
+           }
+           else
+               channel->ch_pfd[which].ch_poll_idx = -1;
 
     return nfd;
 }
@@ -1679,33 +1701,26 @@ channel_poll_setup(int nfd_in, void *fds_in)
     int
 channel_poll_check(int ret_in, void *fds_in)
 {
-    int ret = ret_in;
-    channel_T *channel;
-    struct pollfd *fds = fds_in;
+    int                ret = ret_in;
+    channel_T  *channel;
+    struct     pollfd *fds = fds_in;
+    int                which;
 
     for (channel = first_channel; channel != NULL; channel = channel->ch_next)
-    {
-       if (ret > 0 && channel->ch_sock_idx != -1
-                            && fds[channel->ch_sock_idx].revents & POLLIN)
-       {
-           channel_read(channel, FALSE, "channel_poll_check");
-           --ret;
-       }
 #  ifdef CHANNEL_PIPES
-       if (ret > 0 && channel->ch_out_idx != -1
-                              && fds[channel->ch_out_idx].revents & POLLIN)
-       {
-           channel_read(channel, FALSE, "channel_poll_check");
-           --ret;
-       }
-       if (ret > 0 && channel->ch_err_idx != -1
-                              && fds[channel->ch_err_idx].revents & POLLIN)
+       for (which = CHAN_SOCK; which < CHAN_IN; ++which)
+#  else
+       which = CHAN_SOCK;
+#  endif
        {
-           channel_read(channel, TRUE, "channel_poll_check");
-           --ret;
+           int idx = channel->ch_pfd[which].ch_poll_idx;
+
+           if (ret > 0 && idx != -1 && fds[idx].revents & POLLIN)
+           {
+               channel_read(channel, which, "channel_poll_check");
+               --ret;
+           }
        }
-#  endif
-    }
 
     return ret;
 }
@@ -1718,33 +1733,27 @@ channel_poll_check(int ret_in, void *fds_in)
     int
 channel_select_setup(int maxfd_in, void *rfds_in)
 {
-    int            maxfd = maxfd_in;
-    channel_T *channel;
-    fd_set  *rfds = rfds_in;
+    int                maxfd = maxfd_in;
+    channel_T  *channel;
+    fd_set     *rfds = rfds_in;
+    int                which;
 
     for (channel = first_channel; channel != NULL; channel = channel->ch_next)
-    {
-       if (channel->ch_sock >= 0)
-       {
-           FD_SET(channel->ch_sock, rfds);
-           if (maxfd < channel->ch_sock)
-               maxfd = channel->ch_sock;
-       }
 #  ifdef CHANNEL_PIPES
-       if (channel->ch_out >= 0)
-       {
-           FD_SET(channel->ch_out, rfds);
-           if (maxfd < channel->ch_out)
-               maxfd = channel->ch_out;
-       }
-       if (channel->ch_err >= 0)
+       for (which = CHAN_SOCK; which < CHAN_IN; ++which)
+#  else
+       which = CHAN_SOCK;
+#  endif
        {
-           FD_SET(channel->ch_err, rfds);
-           if (maxfd < channel->ch_err)
-               maxfd = channel->ch_err;
+           sock_T fd = channel->ch_pfd[which].ch_fd;
+
+           if (fd >= 0)
+           {
+               FD_SET(fd, rfds);
+               if (maxfd < fd)
+                   maxfd = fd;
+           }
        }
-#  endif
-    }
 
     return maxfd;
 }
@@ -1755,33 +1764,26 @@ channel_select_setup(int maxfd_in, void *rfds_in)
     int
 channel_select_check(int ret_in, void *rfds_in)
 {
-    int            ret = ret_in;
-    channel_T *channel;
-    fd_set  *rfds = rfds_in;
+    int                ret = ret_in;
+    channel_T  *channel;
+    fd_set     *rfds = rfds_in;
+    int                which;
 
     for (channel = first_channel; channel != NULL; channel = channel->ch_next)
-    {
-       if (ret > 0 && channel->ch_sock >= 0
-                                      && FD_ISSET(channel->ch_sock, rfds))
-       {
-           channel_read(channel, FALSE, "channel_select_check");
-           --ret;
-       }
 #  ifdef CHANNEL_PIPES
-       if (ret > 0 && channel->ch_out >= 0
-                                      && FD_ISSET(channel->ch_out, rfds))
-       {
-           channel_read(channel, FALSE, "channel_select_check");
-           --ret;
-       }
-       if (ret > 0 && channel->ch_err >= 0
-                                      && FD_ISSET(channel->ch_err, rfds))
+       for (which = CHAN_SOCK; which < CHAN_IN; ++which)
+#  else
+       which = CHAN_SOCK;
+#  endif
        {
-           channel_read(channel, TRUE, "channel_select_check");
-           --ret;
+           sock_T fd = channel->ch_pfd[which].ch_fd;
+
+           if (ret > 0 && fd >= 0 && FD_ISSET(fd, rfds))
+           {
+               channel_read(channel, which, "channel_select_check");
+               --ret;
+           }
        }
-#  endif
-    }
 
     return ret;
 }
index 75f5e54b5f665ffdafc44e7f6e366571f60a9ae2..a36f3dd51d0eef34c7a68ac12d2b4ea7ec4cab81 100644 (file)
@@ -9970,12 +9970,12 @@ f_ch_open(typval_T *argvars, typval_T *rettv)
     channel = channel_open((char *)address, port, waittime, NULL);
     if (channel != NULL)
     {
+       rettv->vval.v_channel = channel;
        channel_set_json_mode(channel, ch_mode);
        channel_set_timeout(channel, timeout);
        if (callback != NULL && *callback != NUL)
            channel_set_callback(channel, callback);
     }
-    rettv->vval.v_channel = channel;
 }
 
 /*
index e1f8e27b783428fece63171eaa3fff6f6f9ce565..ca01b064ca5b8b1f6388d98ad7cefeafdb4b36c5 100644 (file)
 #endif
 
 /*
- * The +job feature requires +eval and Unix or MS-Widndows.
+ * The +job feature requires +eval and Unix or MS-Windows.
  */
 #if (defined(UNIX) || defined(WIN32)) && defined(FEAT_EVAL)
 # define FEAT_JOB
index 67274ee18c528afaa430dd723193715be4519cb4..6bafa8e0e467d357055035eec174dbd643f052b2 100644 (file)
@@ -1780,14 +1780,15 @@ process_message(void)
 #ifdef FEAT_CHANNEL
     if (msg.message == WM_NETBEANS)
     {
-       channel_T *channel = channel_fd2channel((sock_T)msg.wParam);
+       int         what;
+       channel_T   *channel = channel_fd2channel((sock_T)msg.wParam, &what);
 
        if (channel != NULL)
        {
            /* Disable error messages, they can mess up the display and throw
             * an exception. */
            ++emsg_off;
-           channel_read(channel, FALSE, "process_message");
+           channel_read(channel, what, "process_message");
            --emsg_off;
        }
        return;
index 01b5a93127cdbe86861247dfc7d2b6687288017d..65a4b9265dccd0039c10788601e876a791ca5d3e 100644 (file)
@@ -5116,10 +5116,15 @@ mch_start_job(char **argv, job_T *job)
     close(fd_err[1]);
     channel_set_pipes(channel, fd_in[1], fd_out[0], fd_err[0]);
     channel_set_job(channel, job);
+#ifdef FEAT_GUI
+    channel_gui_register(channel);
+#endif
 
     return;
 
 failed:
+    if (channel != NULL)
+       channel_free(channel);
     if (fd_in[0] >= 0)
     {
        close(fd_in[0]);
index cc5fc3dee9813be594d112d9743c0def1a5392dd..55d8e6ba1d84b97bc79b2e89e814e3943aaf5a50 100644 (file)
@@ -5039,12 +5039,19 @@ mch_start_job(char *cmd, job_T *job)
     STARTUPINFO                si;
     PROCESS_INFORMATION        pi;
     HANDLE             jo;
+#ifdef FEAT_CHANNEL
+    channel_T  *channel;
+
+    channel = add_channel();
+    if (channel == NULL)
+       return;
+#endif
 
     jo = CreateJobObject(NULL, NULL);
     if (jo == NULL)
     {
        job->jv_status = JOB_FAILED;
-       return;
+       goto failed;
     }
 
     ZeroMemory(&pi, sizeof(pi));
@@ -5062,22 +5069,40 @@ mch_start_job(char *cmd, job_T *job)
     {
        CloseHandle(jo);
        job->jv_status = JOB_FAILED;
+       goto failed;
     }
-    else
+
+    if (!AssignProcessToJobObject(jo, pi.hProcess))
     {
-       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;
+       /* 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;
+
+#ifdef FEAT_CHANNEL
+# if 0
+    /* TODO: connect stdin/stdout/stderr */
+    job->jv_channel = channel;
+    channel_set_pipes(channel, fd_in[1], fd_out[0], fd_err[0]);
+    channel_set_job(channel, job);
+
+#  ifdef FEAT_GUI
+     channel_gui_register(channel);
+#  endif
+# endif
+#endif
+    return;
+
+failed:
+#ifdef FEAT_CHANNEL
+    channel_free(channel);
+#endif
 }
 
     char *
index 56eb887c178151ef31d6301aa1ff27e65a351122..f7480521e27476a0609e5a1e9c6ff0f8c61c0e8c 100644 (file)
@@ -2,6 +2,7 @@
 void ch_logfile(FILE *file);
 channel_T *add_channel(void);
 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 (*close_cb)(void));
 void channel_set_pipes(channel_T *channel, int in, int out, int err);
@@ -21,10 +22,10 @@ char_u *channel_peek(channel_T *channel);
 void channel_clear(channel_T *channel);
 void channel_free_all(void);
 int channel_get_id(void);
-void channel_read(channel_T *channel, int use_stderr, char *func);
+void channel_read(channel_T *channel, int what, char *func);
 char_u *channel_read_block(channel_T *channel);
 int channel_read_json_block(channel_T *channel, int id, typval_T **rettv);
-channel_T *channel_fd2channel(sock_T fd);
+channel_T *channel_fd2channel(sock_T fd, int *what);
 int channel_send(channel_T *channel, char_u *buf, char *fun);
 int channel_poll_setup(int nfd_in, void *fds_in);
 int channel_poll_check(int ret_in, void *fds_in);
index c8334cbea997d949c13e60e9351e7db8850252c5..7dd4b46bdd657af29cd6376d441bf35c74764a00 100644 (file)
@@ -1301,35 +1301,30 @@ typedef enum
     MODE_JS
 } ch_mode_T;
 
-struct channel_S {
-    channel_T  *ch_next;
-    channel_T  *ch_prev;
-
-    int                ch_id;          /* ID of the channel */
+/* Ordering matters: IN is last, only SOCK/OUT/ERR are polled */
 
-    sock_T     ch_sock;        /* the socket, -1 for a closed channel */
+#define CHAN_SOCK   0
+#define CH_SOCK            ch_pfd[CHAN_SOCK].ch_fd
 
 #ifdef UNIX
 # define CHANNEL_PIPES
-    int                ch_in;          /* stdin of the job, -1 if not used */
-    int                ch_out;         /* stdout of the job, -1 if not used */
-    int                ch_err;         /* stderr of the job, -1 if not used */
 
-# if defined(UNIX) && !defined(HAVE_SELECT)
-    int                ch_sock_idx;    /* used by channel_poll_setup() */
-    int                ch_in_idx;      /* used by channel_poll_setup() */
-    int                ch_out_idx;     /* used by channel_poll_setup() */
-    int                ch_err_idx;     /* used by channel_poll_setup() */
-# endif
+# define CHAN_OUT   1
+# define CHAN_ERR   2
+# define CHAN_IN    3
+# define CH_OUT            ch_pfd[CHAN_OUT].ch_fd
+# define CH_ERR            ch_pfd[CHAN_ERR].ch_fd
+# define CH_IN     ch_pfd[CHAN_IN].ch_fd
 #endif
 
-    readq_T    ch_head;        /* dummy node, header for circular queue */
+/* The per-fd info for a channel. */
+typedef struct {
+    sock_T     ch_fd;      /* socket/stdin/stdout/stderr, -1 if not used */
+
+# if defined(UNIX) && !defined(HAVE_SELECT)
+    int                ch_poll_idx;    /* used by channel_poll_setup() */
+# endif
 
-    int                ch_error;       /* When TRUE an error was reported.  Avoids
-                                * giving pages full of error messages when
-                                * the other side has exited, only mention the
-                                * first error until the connection works
-                                * again. */
 #ifdef FEAT_GUI_X11
     XtInputId  ch_inputHandler; /* Cookie for input */
 #endif
@@ -1337,9 +1332,25 @@ struct channel_S {
     gint       ch_inputHandler; /* Cookie for input */
 #endif
 #ifdef WIN32
-    int                ch_inputHandler; /* simply ret.value of WSAAsyncSelect() */
+    int                ch_inputHandler; /* ret.value of WSAAsyncSelect() */
 #endif
+} chan_fd_T;
+
+struct channel_S {
+    channel_T  *ch_next;
+    channel_T  *ch_prev;
+
+    int                ch_id;          /* ID of the channel */
+
+    chan_fd_T  ch_pfd[4];      /* info for socket, in, out and err */
 
+    readq_T    ch_head;        /* dummy node, header for circular queue */
+
+    int                ch_error;       /* When TRUE an error was reported.  Avoids
+                                * giving pages full of error messages when
+                                * the other side has exited, only mention the
+                                * first error until the connection works
+                                * again. */
     void       (*ch_close_cb)(void); /* callback for when channel is closed */
 
     int                ch_block_id;    /* ID that channel_read_json_block() is
index f1abf12dea96f55c6e9976603f0911647778b7e2..5557b7451e7f6b52b967882f7e5abfd0c0b8d460 100644 (file)
@@ -747,6 +747,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1318,
 /**/
     1317,
 /**/