To: vim_dev@googlegroups.com Subject: Patch 7.4.1458 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.1458 Problem: When a JSON channel has a callback it may never be cleared. Solution: Do not write "DETACH" into a JS or JSON channel. Files: src/channel.c *** ../vim-7.4.1457/src/channel.c 2016-02-28 20:51:44.549531370 +0100 --- src/channel.c 2016-02-28 22:12:53.710097047 +0100 *************** *** 316,335 **** * Called when the refcount of a channel is zero. * Return TRUE if "channel" has a callback and the associated job wasn't * killed. - * If the job was killed the channel is not expected to work anymore. - * If there is no callback then nobody can get readahead. */ static int channel_still_useful(channel_T *channel) { if (channel->ch_job_killed && channel->ch_job == NULL) return FALSE; ! return channel->ch_callback != NULL #ifdef CHANNEL_PIPES ! || channel->ch_part[PART_OUT].ch_callback != NULL ! || channel->ch_part[PART_ERR].ch_callback != NULL #endif ! || channel->ch_close_cb != NULL; } /* --- 316,362 ---- * Called when the refcount of a channel is zero. * Return TRUE if "channel" has a callback and the associated job wasn't * killed. */ static int channel_still_useful(channel_T *channel) { + int has_sock_msg; + #ifdef CHANNEL_PIPES + int has_out_msg; + int has_err_msg; + #endif + + /* If the job was killed the channel is not expected to work anymore. */ if (channel->ch_job_killed && channel->ch_job == NULL) return FALSE; ! ! /* If there is a close callback it may still need to be invoked. */ ! if (channel->ch_close_cb != NULL) ! return TRUE; ! ! /* If there is no callback then nobody can get readahead. If the fd is ! * closed and there is no readahead then the callback won't be called. */ ! has_sock_msg = channel->ch_part[PART_SOCK].ch_fd != INVALID_FD ! || channel->ch_part[PART_SOCK].ch_head.rq_next != NULL ! || channel->ch_part[PART_SOCK].ch_json_head.jq_next != NULL; ! #ifdef CHANNEL_PIPES ! has_out_msg = channel->ch_part[PART_OUT].ch_fd != INVALID_FD ! || channel->ch_part[PART_OUT].ch_head.rq_next != NULL ! || channel->ch_part[PART_OUT].ch_json_head.jq_next != NULL; ! has_err_msg = channel->ch_part[PART_ERR].ch_fd != INVALID_FD ! || channel->ch_part[PART_ERR].ch_head.rq_next != NULL ! || channel->ch_part[PART_ERR].ch_json_head.jq_next != NULL; ! #endif ! return (channel->ch_callback != NULL && (has_sock_msg ! #ifdef CHANNEL_PIPES ! || has_out_msg || has_err_msg ! #endif ! )) #ifdef CHANNEL_PIPES ! || (channel->ch_part[PART_OUT].ch_callback != NULL && has_out_msg) ! || (channel->ch_part[PART_ERR].ch_callback != NULL && has_err_msg) #endif ! ; } /* *************** *** 1497,1503 **** { if (item->cq_seq_nr == seq_nr) { ! ch_logs(channel, "Invoking one-time callback '%s'", (char *)item->cq_callback); /* Remove the item from the list first, if the callback * invokes ch_close() the list will be cleared. */ --- 1524,1530 ---- { if (item->cq_seq_nr == seq_nr) { ! ch_logs(channel, "Invoking one-time callback %s", (char *)item->cq_callback); /* Remove the item from the list first, if the callback * invokes ch_close() the list will be cleared. */ *************** *** 1558,1564 **** if (callback != NULL) { /* invoke the channel callback */ ! ch_log(channel, "Invoking channel callback"); invoke_callback(channel, callback, argv); } } --- 1585,1591 ---- if (callback != NULL) { /* invoke the channel callback */ ! ch_logs(channel, "Invoking channel callback %s", (char *)callback); invoke_callback(channel, callback, argv); } } *************** *** 1758,1764 **** /* Sent when the channel is found closed when reading. */ #define DETACH_MSG_RAW "DETACH\n" - #define DETACH_MSG_JSON "\"DETACH\"\n" /* Buffer size for reading incoming messages. */ #define MAXMSGSIZE 4096 --- 1785,1790 ---- *************** *** 1854,1860 **** int readlen = 0; sock_T fd; int use_socket = FALSE; - char *msg; fd = channel->ch_part[part].ch_fd; if (fd == INVALID_FD) --- 1880,1885 ---- *************** *** 1909,1919 **** * -> ui_breakcheck * -> gui event loop or select loop * -> channel_read() */ ! msg = channel->ch_part[part].ch_mode == MODE_RAW ! || channel->ch_part[part].ch_mode == MODE_NL ! ? DETACH_MSG_RAW : DETACH_MSG_JSON; ! channel_save(channel, part, (char_u *)msg, (int)STRLEN(msg)); /* TODO: When reading from stdout is not possible, should we try to * keep stdin and stderr open? Probably not, assume the other side --- 1934,1945 ---- * -> ui_breakcheck * -> gui event loop or select loop * -> channel_read() + * Don't send "DETACH" for a JS or JSON channel. */ ! if (channel->ch_part[part].ch_mode == MODE_RAW ! || channel->ch_part[part].ch_mode == MODE_NL) ! channel_save(channel, part, (char_u *)DETACH_MSG_RAW, ! (int)STRLEN(DETACH_MSG_RAW)); /* TODO: When reading from stdout is not possible, should we try to * keep stdin and stderr open? Probably not, assume the other side *** ../vim-7.4.1457/src/version.c 2016-02-28 20:51:44.553531328 +0100 --- src/version.c 2016-02-28 22:19:47.597737477 +0100 *************** *** 745,746 **** --- 745,748 ---- { /* Add new patch number below this line */ + /**/ + 1458, /**/ -- Wi n0t trei a h0liday in Sweden thi yer? "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// 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 ///