diff options
author | Bram Moolenaar <Bram@vim.org> | 2016-04-26 20:30:07 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2016-04-26 20:30:07 +0200 |
commit | 674127e1801fd02ff07dddf0dc3bf0d8cce68997 (patch) | |
tree | 1fcc42ec815223e3f3015cbf10dc9b530890220f | |
parent | 6231cb8b5b208becf088531816027001acc754e5 (diff) |
patch 7.4.1791v7.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.
-rw-r--r-- | src/channel.c | 17 | ||||
-rw-r--r-- | src/version.c | 2 |
2 files changed, 14 insertions, 5 deletions
diff --git a/src/channel.c b/src/channel.c index 1ebb675d50..1be3d27ffe 100644 --- a/src/channel.c +++ b/src/channel.c @@ -439,7 +439,8 @@ free_unused_channels_contents(int copyID, int mask) 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 mask) 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 index cd760ab6ca..a2553e6938 100644 --- 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, |