changeset 9011:72a597e9e36d v7.4.1791

commit https://github.com/vim/vim/commit/674127e1801fd02ff07dddf0dc3bf0d8cce68997 Author: Bram Moolenaar <Bram@vim.org> Date: Tue Apr 26 20:30:07 2016 +0200 patch 7.4.1791 Problem: Channel could be garbage collected too early. Solution: Don't free a channel or remove it from a job when it is still useful.
author Christian Brabandt <cb@256bit.org>
date Tue, 26 Apr 2016 20:45:05 +0200
parents 4e61ef434a1e
children 3390e71380fa
files src/channel.c src/version.c
diffstat 2 files changed, 14 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/channel.c
+++ b/src/channel.c
@@ -439,7 +439,8 @@ free_unused_channels_contents(int copyID
     channel_T	*ch;
 
     for (ch = first_channel; ch != NULL; ch = ch->ch_next)
-	if ((ch->ch_copyID & mask) != (copyID & mask))
+	if (!channel_still_useful(ch)
+				 && (ch->ch_copyID & mask) != (copyID & mask))
 	{
 	    /* Free the channel and ordinary items it contains, but don't
 	     * recurse into Lists, Dictionaries etc. */
@@ -458,7 +459,8 @@ free_unused_channels(int copyID, int mas
     for (ch = first_channel; ch != NULL; ch = ch_next)
     {
 	ch_next = ch->ch_next;
-	if ((ch->ch_copyID & mask) != (copyID & mask))
+	if (!channel_still_useful(ch)
+				 && (ch->ch_copyID & mask) != (copyID & mask))
 	{
 	    /* Free the channel struct itself. */
 	    channel_free_channel(ch);
@@ -4079,13 +4081,16 @@ job_free(job_T *job)
 
 /*
  * Return TRUE if the job should not be freed yet.  Do not free the job when
- * it has not ended yet and there is a "stoponexit" flag or an exit callback.
+ * it has not ended yet and there is a "stoponexit" flag, an exit callback
+ * or when the associated channel will do something with the job output.
  */
     static int
 job_still_useful(job_T *job)
 {
     return job->jv_status == JOB_STARTED
-		   && (job->jv_stoponexit != NULL || job->jv_exit_cb != NULL);
+	       && (job->jv_stoponexit != NULL || job->jv_exit_cb != NULL
+		   || (job->jv_channel != NULL
+		       && channel_still_useful(job->jv_channel)));
 }
 
     void
@@ -4099,10 +4104,12 @@ job_unref(job_T *job)
 	{
 	    job_free(job);
 	}
-	else if (job->jv_channel != NULL)
+	else if (job->jv_channel != NULL
+				    && !channel_still_useful(job->jv_channel))
 	{
 	    /* Do remove the link to the channel, otherwise it hangs
 	     * around until Vim exits. See job_free() for refcount. */
+	    ch_log(job->jv_channel, "detaching channel from job");
 	    job->jv_channel->ch_job = NULL;
 	    channel_unref(job->jv_channel);
 	    job->jv_channel = NULL;
--- a/src/version.c
+++ b/src/version.c
@@ -754,6 +754,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1791,
+/**/
     1790,
 /**/
     1789,