Mercurial > vim
diff src/channel.c @ 8257:c4ffdda8cdfd v7.4.1421
commit https://github.com/vim/vim/commit/c8dcbb12c5d7f3eb0c334daebb4475bb015b91e7
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Feb 25 23:10:17 2016 +0100
patch 7.4.1421
Problem: May free a channel when a callback may need to be invoked.
Solution: Keep the channel when refcount is zero.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 25 Feb 2016 23:15:05 +0100 |
parents | 60586ce747c4 |
children | 99a70c3b902f |
line wrap: on
line diff
--- a/src/channel.c +++ b/src/channel.c @@ -307,6 +307,31 @@ add_channel(void) } /* + * Return TRUE if "channel" has a callback. + */ + static int +channel_has_callback(channel_T *channel) +{ + 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; +} + +/* + * Close a channel and free all its resources if there is no further action + * possible, there is no callback to be invoked. + */ + void +channel_may_free(channel_T *channel) +{ + if (!channel_has_callback(channel)) + channel_free(channel); +} + +/* * Close a channel and free all its resources. */ void @@ -1463,7 +1488,7 @@ channel_status(channel_T *channel) /* * Close channel "channel". - * This does not trigger the close callback. + * Trigger the close callback if "invoke_close_cb" is TRUE. */ void channel_close(channel_T *channel, int invoke_close_cb) @@ -2149,6 +2174,14 @@ channel_parse_messages(void) while (channel != NULL) { + if (channel->ch_refcount == 0 && !channel_has_callback(channel)) + { + /* channel is no longer useful, free it */ + channel_free(channel); + channel = first_channel; + part = PART_SOCK; + continue; + } if (channel->ch_part[part].ch_fd != INVALID_FD) { /* Increase the refcount, in case the handler causes the channel