# HG changeset patch # User Christian Brabandt # Date 1461696305 -7200 # Node ID 72a597e9e36d64bfc9f8e5a0b1783fbd1f233f7d # Parent 4e61ef434a1ebea4d2dbedf4cd0d9f3c09bc07e4 commit https://github.com/vim/vim/commit/674127e1801fd02ff07dddf0dc3bf0d8cce68997 Author: Bram Moolenaar 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. diff --git a/src/channel.c b/src/channel.c --- 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; diff --git a/src/version.c b/src/version.c --- 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,