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