To: vim_dev@googlegroups.com Subject: Patch 7.4.1318 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.1318 Problem: Channel with pipes doesn't work in GUI. Solution: Register input handlers for pipes. Files: src/structs.h, src/feature.h, src/channel.c, src/eval.c, src/os_unix.c, src/os_win32.c, src/gui_w48.c, src/proto/channel.pro *** ../vim-7.4.1317/src/structs.h 2016-02-13 23:22:35.077363718 +0100 --- src/structs.h 2016-02-14 19:05:06.792167742 +0100 *************** *** 1301,1335 **** MODE_JS } ch_mode_T; ! struct channel_S { ! channel_T *ch_next; ! channel_T *ch_prev; ! ! int ch_id; /* ID of the channel */ ! sock_T ch_sock; /* the socket, -1 for a closed channel */ #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 #endif ! 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. */ #ifdef FEAT_GUI_X11 XtInputId ch_inputHandler; /* Cookie for input */ #endif --- 1301,1330 ---- MODE_JS } ch_mode_T; ! /* Ordering matters: IN is last, only SOCK/OUT/ERR are polled */ ! #define CHAN_SOCK 0 ! #define CH_SOCK ch_pfd[CHAN_SOCK].ch_fd #ifdef UNIX # define CHANNEL_PIPES ! # 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 ! /* 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 #ifdef FEAT_GUI_X11 XtInputId ch_inputHandler; /* Cookie for input */ #endif *************** *** 1337,1345 **** gint ch_inputHandler; /* Cookie for input */ #endif #ifdef WIN32 ! int ch_inputHandler; /* simply ret.value of WSAAsyncSelect() */ #endif void (*ch_close_cb)(void); /* callback for when channel is closed */ int ch_block_id; /* ID that channel_read_json_block() is --- 1332,1356 ---- gint ch_inputHandler; /* Cookie for input */ #endif #ifdef WIN32 ! 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 *** ../vim-7.4.1317/src/feature.h 2016-02-07 19:57:12.192788494 +0100 --- src/feature.h 2016-02-13 23:45:26.674898639 +0100 *************** *** 1262,1268 **** #endif /* ! * The +job feature requires +eval and Unix or MS-Widndows. */ #if (defined(UNIX) || defined(WIN32)) && defined(FEAT_EVAL) # define FEAT_JOB --- 1262,1268 ---- #endif /* ! * The +job feature requires +eval and Unix or MS-Windows. */ #if (defined(UNIX) || defined(WIN32)) && defined(FEAT_EVAL) # define FEAT_JOB *** ../vim-7.4.1317/src/channel.c 2016-02-13 23:22:35.085363634 +0100 --- src/channel.c 2016-02-14 19:04:42.060425893 +0100 *************** *** 213,219 **** channel_T * add_channel(void) { ! channel_T *channel = (channel_T *)alloc_clear((int)sizeof(channel_T)); if (channel == NULL) return NULL; --- 213,220 ---- channel_T * add_channel(void) { ! int which; ! channel_T *channel = (channel_T *)alloc_clear((int)sizeof(channel_T)); if (channel == NULL) return NULL; *************** *** 221,241 **** 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; #endif #ifdef FEAT_GUI_X11 ! channel->ch_inputHandler = (XtInputId)NULL; #endif #ifdef FEAT_GUI_GTK ! channel->ch_inputHandler = 0; #endif #ifdef FEAT_GUI_W32 ! channel->ch_inputHandler = -1; #endif channel->ch_timeout = 2000; --- 222,244 ---- channel->ch_id = next_ch_id++; ch_log(channel, "Opening channel\n"); #ifdef CHANNEL_PIPES ! 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_pfd[which].ch_inputHandler = (XtInputId)NULL; #endif #ifdef FEAT_GUI_GTK ! channel->ch_pfd[which].ch_inputHandler = 0; #endif #ifdef FEAT_GUI_W32 ! channel->ch_pfd[which].ch_inputHandler = -1; #endif + } channel->ch_timeout = 2000; *************** *** 290,296 **** if (channel == NULL) ch_errorn(NULL, "Channel %d not found", id); else ! channel_read(channel, FALSE, "messageFromNetbeans"); } #endif --- 293,299 ---- if (channel == NULL) ch_errorn(NULL, "Channel %d not found", id); else ! channel_read(channel, -1, "messageFromNetbeans"); } #endif *************** *** 318,363 **** #endif static void ! channel_gui_register(channel_T *channel) { - 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); # 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); # 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); # endif # endif # endif } /* * Register any of our file descriptors with the GUI event handling system. * Called when the GUI has started. --- 321,377 ---- #endif static void ! channel_gui_register_one(channel_T *channel, int which) { # ifdef FEAT_GUI_X11 ! /* 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_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_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 + } + /* * Register any of our file descriptors with the GUI event handling system. * Called when the GUI has started. *************** *** 368,407 **** channel_T *channel; for (channel = first_channel; channel != NULL; channel = channel->ch_next) ! /* TODO: pipes */ ! if (channel->ch_sock >= 0) ! channel_gui_register(channel); } static void ! channel_gui_unregister(channel_T *channel) { - /* TODO: pipes */ # ifdef FEAT_GUI_X11 ! if (channel->ch_inputHandler != (XtInputId)NULL) { ! XtRemoveInput(channel->ch_inputHandler); ! channel->ch_inputHandler = (XtInputId)NULL; } # else # ifdef FEAT_GUI_GTK ! if (channel->ch_inputHandler != 0) { ! gdk_input_remove(channel->ch_inputHandler); ! channel->ch_inputHandler = 0; } # else # ifdef FEAT_GUI_W32 ! if (channel->ch_inputHandler == 0) { ! WSAAsyncSelect(channel->ch_sock, s_hwnd, 0, 0); ! channel->ch_inputHandler = -1; } # endif # endif # endif } #endif /* --- 382,431 ---- channel_T *channel; for (channel = first_channel; channel != NULL; channel = channel->ch_next) ! channel_gui_register(channel); } static void ! channel_gui_unregister_one(channel_T *channel, int which) { # ifdef FEAT_GUI_X11 ! if (channel->ch_pfd[which].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_pfd[which].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_pfd[which].ch_inputHandler == 0) { ! 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,445 **** --- 464,470 ---- { ch_error(NULL, "in socket() in channel_open().\n"); PERROR("E898: socket() in channel_open()"); + channel_free(channel); return NULL; } *************** *** 453,458 **** --- 478,484 ---- 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,477 **** --- 498,504 ---- ch_errorn(NULL, "channel_open: Connect failed with errno %d\n", errno); sock_close(sd); + channel_free(channel); return NULL; } } *************** *** 492,497 **** --- 519,525 ---- errno); PERROR(_("E902: Cannot connect to port")); sock_close(sd); + channel_free(channel); return NULL; } } *************** *** 513,524 **** --- 541,554 ---- 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,547 **** --- 572,578 ---- 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,586 **** ch_error(NULL, "Cannot connect to port after retry\n"); PERROR(_("E899: Cannot connect to port after retry2")); sock_close(sd); return NULL; } } } ! channel->ch_sock = sd; channel->ch_close_cb = close_cb; #ifdef FEAT_GUI --- 606,618 ---- 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_close_cb = close_cb; #ifdef FEAT_GUI *************** *** 594,602 **** 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; } #endif --- 626,634 ---- 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; } #endif *************** *** 1115,1123 **** int channel_can_write_to(channel_T *channel) { ! return channel != NULL && (channel->ch_sock >= 0 #ifdef CHANNEL_PIPES ! || channel->ch_in >= 0 #endif ); } --- 1147,1155 ---- int channel_can_write_to(channel_T *channel) { ! return channel != NULL && (channel->CH_SOCK >= 0 #ifdef CHANNEL_PIPES ! || channel->CH_IN >= 0 #endif ); } *************** *** 1129,1139 **** int channel_is_open(channel_T *channel) { ! return channel != NULL && (channel->ch_sock >= 0 #ifdef CHANNEL_PIPES ! || channel->ch_in >= 0 ! || channel->ch_out >= 0 ! || channel->ch_err >= 0 #endif ); } --- 1161,1171 ---- int channel_is_open(channel_T *channel) { ! return channel != NULL && (channel->CH_SOCK >= 0 #ifdef CHANNEL_PIPES ! || channel->CH_IN >= 0 ! || channel->CH_OUT >= 0 ! || channel->CH_ERR >= 0 #endif ); } *************** *** 1160,1169 **** { ch_log(channel, "Closing channel"); ! if (channel->ch_sock >= 0) { ! sock_close(channel->ch_sock); ! channel->ch_sock = -1; channel->ch_close_cb = NULL; #ifdef FEAT_GUI channel_gui_unregister(channel); --- 1192,1201 ---- { ch_log(channel, "Closing channel"); ! if (channel->CH_SOCK >= 0) { ! sock_close(channel->CH_SOCK); ! channel->CH_SOCK = -1; channel->ch_close_cb = NULL; #ifdef FEAT_GUI channel_gui_unregister(channel); *************** *** 1172,1191 **** channel->ch_callback = NULL; } #if defined(CHANNEL_PIPES) ! if (channel->ch_in >= 0) { ! close(channel->ch_in); ! channel->ch_in = -1; } ! if (channel->ch_out >= 0) { ! close(channel->ch_out); ! channel->ch_out = -1; } ! if (channel->ch_err >= 0) { ! close(channel->ch_err); ! channel->ch_err = -1; } #endif channel_clear(channel); --- 1204,1223 ---- channel->ch_callback = NULL; } #if defined(CHANNEL_PIPES) ! if (channel->CH_IN >= 0) { ! close(channel->CH_IN); ! channel->CH_IN = -1; } ! if (channel->CH_OUT >= 0) { ! close(channel->CH_OUT); ! channel->CH_OUT = -1; } ! if (channel->CH_ERR >= 0) { ! close(channel->CH_ERR); ! channel->CH_ERR = -1; } #endif channel_clear(channel); *************** *** 1351,1367 **** /* * Get the file descriptor to read from, either the socket or stdout. */ static int ! get_read_fd(channel_T *channel, int use_stderr) { ! 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; #endif ch_error(channel, "channel_read() called while socket is closed\n"); return -1; --- 1383,1398 ---- /* * Get the file descriptor to read from, either the socket or stdout. + * TODO: never gets stderr. */ static int ! get_read_fd(channel_T *channel) { ! if (channel->CH_SOCK >= 0) ! return channel->CH_SOCK; #if defined(CHANNEL_PIPES) ! if (channel->CH_OUT >= 0) ! return channel->CH_OUT; #endif ch_error(channel, "channel_read() called while socket is closed\n"); return -1; *************** *** 1369,1378 **** /* * Read from channel "channel" for as long as there is something to read. * The data is put in the read queue. */ void ! channel_read(channel_T *channel, int use_stderr, char *func) { static char_u *buf = NULL; int len = 0; --- 1400,1410 ---- /* * 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 which, char *func) { static char_u *buf = NULL; int len = 0; *************** *** 1380,1389 **** int fd; int use_socket = FALSE; ! fd = get_read_fd(channel, use_stderr); if (fd < 0) return; ! use_socket = channel->ch_sock >= 0; /* Allocate a buffer to read into. */ if (buf == NULL) --- 1412,1424 ---- int fd; int use_socket = FALSE; ! if (which < 0) ! fd = get_read_fd(channel); ! else ! fd = channel->ch_pfd[which].ch_fd; if (fd < 0) return; ! use_socket = fd == channel->CH_SOCK; /* Allocate a buffer to read into. */ if (buf == NULL) *************** *** 1450,1456 **** else { close(fd); ! channel->ch_out = -1; } #endif --- 1485,1491 ---- else { close(fd); ! channel->CH_OUT = -1; } #endif *************** *** 1480,1492 **** ch_log(channel, "Reading raw\n"); if (channel_peek(channel) == NULL) { ! int fd = get_read_fd(channel, FALSE); 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"); } /* TODO: only get the first message */ --- 1515,1528 ---- ch_log(channel, "Reading raw\n"); if (channel_peek(channel) == NULL) { ! 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, -1, "channel_read_block"); } /* TODO: only get the first message */ *************** *** 1526,1536 **** continue; /* Wait for up to the channel timeout. */ ! fd = get_read_fd(channel, FALSE); if (fd < 0 || channel_wait(channel, fd, channel->ch_timeout) == FAIL) break; ! channel_read(channel, FALSE, "channel_read_json_block"); } } channel->ch_block_id = 0; --- 1562,1572 ---- continue; /* Wait for up to the channel timeout. */ ! fd = get_read_fd(channel); if (fd < 0 || channel_wait(channel, fd, channel->ch_timeout) == FAIL) break; ! channel_read(channel, -1, "channel_read_json_block"); } } channel->ch_block_id = 0; *************** *** 1539,1562 **** # if defined(WIN32) || defined(PROTO) /* ! * Lookup the channel from the socket. * Returns NULL when the socket isn't found. */ channel_T * ! channel_fd2channel(sock_T fd) { ! channel_T *channel; 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 # endif ! ) ! return channel; return NULL; } # endif --- 1575,1602 ---- # if defined(WIN32) || defined(PROTO) /* ! * 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, int *whichp) { ! channel_T *channel; ! int i; if (fd >= 0) for (channel = first_channel; channel != NULL; channel = channel->ch_next) ! # ifdef CHANNEL_PIPES ! for (i = CHAN_SOCK; i < CHAN_IN; ++i) ! # else ! i = CHAN_SOCK; # endif ! if (channel->ch_pfd[i].ch_fd == fd) ! { ! *whichp = i; ! return channel ! } return NULL; } # endif *************** *** 1574,1587 **** int fd = -1; int use_socket = FALSE; ! if (channel->ch_sock >= 0) { ! fd = channel->ch_sock; use_socket = TRUE; } #if defined(CHANNEL_PIPES) ! else if (channel->ch_in >= 0) ! fd = channel->ch_in; #endif if (fd < 0) { --- 1614,1627 ---- int fd = -1; int use_socket = FALSE; ! if (channel->CH_SOCK >= 0) { ! fd = channel->CH_SOCK; use_socket = TRUE; } #if defined(CHANNEL_PIPES) ! else if (channel->CH_IN >= 0) ! fd = channel->CH_IN; #endif if (fd < 0) { *************** *** 1631,1674 **** int channel_poll_setup(int nfd_in, void *fds_in) { ! int nfd = nfd_in; ! channel_T *channel; ! struct pollfd *fds = fds_in; 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; # endif ! } return nfd; } --- 1671,1696 ---- int channel_poll_setup(int nfd_in, void *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) # ifdef CHANNEL_PIPES ! 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,1711 **** int channel_poll_check(int ret_in, void *fds_in) { ! int ret = ret_in; ! channel_T *channel; ! struct pollfd *fds = fds_in; 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) { ! channel_read(channel, TRUE, "channel_poll_check"); ! --ret; } - # endif - } return ret; } --- 1701,1726 ---- int channel_poll_check(int ret_in, void *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) # ifdef CHANNEL_PIPES ! for (which = CHAN_SOCK; which < CHAN_IN; ++which) ! # else ! which = CHAN_SOCK; ! # endif { ! 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; ! } } return ret; } *************** *** 1718,1750 **** int channel_select_setup(int maxfd_in, void *rfds_in) { ! int maxfd = maxfd_in; ! channel_T *channel; ! fd_set *rfds = rfds_in; 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) { ! FD_SET(channel->ch_err, rfds); ! if (maxfd < channel->ch_err) ! maxfd = channel->ch_err; } - # endif - } return maxfd; } --- 1733,1759 ---- int channel_select_setup(int maxfd_in, void *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) # ifdef CHANNEL_PIPES ! for (which = CHAN_SOCK; which < CHAN_IN; ++which) ! # else ! which = CHAN_SOCK; ! # endif { ! sock_T fd = channel->ch_pfd[which].ch_fd; ! ! if (fd >= 0) ! { ! FD_SET(fd, rfds); ! if (maxfd < fd) ! maxfd = fd; ! } } return maxfd; } *************** *** 1755,1787 **** int channel_select_check(int ret_in, void *rfds_in) { ! int ret = ret_in; ! channel_T *channel; ! fd_set *rfds = rfds_in; 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)) { ! channel_read(channel, TRUE, "channel_select_check"); ! --ret; } - # endif - } return ret; } --- 1764,1789 ---- int channel_select_check(int ret_in, void *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) # ifdef CHANNEL_PIPES ! for (which = CHAN_SOCK; which < CHAN_IN; ++which) ! # else ! which = CHAN_SOCK; ! # endif { ! 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; ! } } return ret; } *** ../vim-7.4.1317/src/eval.c 2016-02-13 23:50:03.743961279 +0100 --- src/eval.c 2016-02-14 00:11:04.998605012 +0100 *************** *** 9970,9981 **** channel = channel_open((char *)address, port, waittime, NULL); if (channel != NULL) { 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; } /* --- 9970,9981 ---- 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); } } /* *** ../vim-7.4.1317/src/os_unix.c 2016-02-13 23:28:17.637753771 +0100 --- src/os_unix.c 2016-02-14 13:42:05.002296825 +0100 *************** *** 5116,5125 **** --- 5116,5130 ---- 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]); *** ../vim-7.4.1317/src/os_win32.c 2016-02-12 19:30:20.353885756 +0100 --- src/os_win32.c 2016-02-14 13:44:21.720867994 +0100 *************** *** 5039,5050 **** STARTUPINFO si; PROCESS_INFORMATION pi; HANDLE jo; jo = CreateJobObject(NULL, NULL); if (jo == NULL) { job->jv_status = JOB_FAILED; ! return; } ZeroMemory(&pi, sizeof(pi)); --- 5039,5057 ---- 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; ! goto failed; } ZeroMemory(&pi, sizeof(pi)); *************** *** 5062,5083 **** { CloseHandle(jo); job->jv_status = JOB_FAILED; } ! else { ! 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; } } char * --- 5069,5108 ---- { CloseHandle(jo); job->jv_status = JOB_FAILED; + goto failed; } ! ! 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; + + #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 * *** ../vim-7.4.1317/src/gui_w48.c 2016-02-13 23:22:35.093363549 +0100 --- src/gui_w48.c 2016-02-14 14:07:47.998167014 +0100 *************** *** 1780,1793 **** #ifdef FEAT_CHANNEL if (msg.message == WM_NETBEANS) { ! channel_T *channel = channel_fd2channel((sock_T)msg.wParam); if (channel != NULL) { /* Disable error messages, they can mess up the display and throw * an exception. */ ++emsg_off; ! channel_read(channel, FALSE, "process_message"); --emsg_off; } return; --- 1780,1794 ---- #ifdef FEAT_CHANNEL if (msg.message == WM_NETBEANS) { ! 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, what, "process_message"); --emsg_off; } return; *** ../vim-7.4.1317/src/proto/channel.pro 2016-02-13 23:22:35.093363549 +0100 --- src/proto/channel.pro 2016-02-14 14:29:38.320487534 +0100 *************** *** 2,7 **** --- 2,8 ---- 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,30 **** 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); 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); 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); --- 22,31 ---- void channel_clear(channel_T *channel); void channel_free_all(void); int channel_get_id(void); ! 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, 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); *** ../vim-7.4.1317/src/version.c 2016-02-14 00:19:55.088992301 +0100 --- src/version.c 2016-02-14 19:06:22.015378080 +0100 *************** *** 749,750 **** --- 749,752 ---- { /* Add new patch number below this line */ + /**/ + 1318, /**/ -- Emacs is a nice OS - but it lacks a good text editor. That's why I am using Vim. --Anonymous /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///