diff options
author | Bram Moolenaar <Bram@vim.org> | 2016-02-28 22:21:38 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2016-02-28 22:21:38 +0100 |
commit | fdd6ce4a2f922afac7bd719a00228dbd8539b9c4 (patch) | |
tree | 8793c18d81b024baa1deadc7595a47af6d079820 /src/channel.c | |
parent | d42119fff228434fe57e88d501c744de0a9fb1b1 (diff) | |
download | vim-git-fdd6ce4a2f922afac7bd719a00228dbd8539b9c4.tar.gz |
patch 7.4.1458v7.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.
Diffstat (limited to 'src/channel.c')
-rw-r--r-- | src/channel.c | 54 |
1 files changed, 40 insertions, 14 deletions
diff --git a/src/channel.c b/src/channel.c index 61156be38..745d226a2 100644 --- a/src/channel.c +++ b/src/channel.c @@ -316,20 +316,47 @@ add_channel(void) * 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) { + 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; - return channel->ch_callback != NULL + + /* 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 - || channel->ch_part[PART_ERR].ch_callback != NULL + || (channel->ch_part[PART_OUT].ch_callback != NULL && has_out_msg) + || (channel->ch_part[PART_ERR].ch_callback != NULL && has_err_msg) #endif - || channel->ch_close_cb != NULL; + ; } /* @@ -1497,7 +1524,7 @@ may_invoke_callback(channel_T *channel, int part) { if (item->cq_seq_nr == seq_nr) { - ch_logs(channel, "Invoking one-time callback '%s'", + 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,7 +1585,7 @@ may_invoke_callback(channel_T *channel, int part) if (callback != NULL) { /* invoke the channel callback */ - ch_log(channel, "Invoking channel callback"); + ch_logs(channel, "Invoking channel callback %s", (char *)callback); invoke_callback(channel, callback, argv); } } @@ -1758,7 +1785,6 @@ channel_free_all(void) /* 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 @@ -1854,7 +1880,6 @@ channel_read(channel_T *channel, int part, char *func) int readlen = 0; sock_T fd; int use_socket = FALSE; - char *msg; fd = channel->ch_part[part].ch_fd; if (fd == INVALID_FD) @@ -1909,11 +1934,12 @@ channel_read(channel_T *channel, int part, char *func) * -> ui_breakcheck * -> gui event loop or select loop * -> channel_read() + * Don't send "DETACH" for a JS or JSON channel. */ - 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)); + 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 |