diff options
author | Bram Moolenaar <Bram@vim.org> | 2016-05-01 14:22:16 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2016-05-01 14:22:16 +0200 |
commit | b8d4905592fc26fcd09180d7d6bfefd899f2f6c6 (patch) | |
tree | 833fcd9fd0bc16a1951144d4e1f9f99a96c97121 /src | |
parent | 9b4ebc692d77ca8ef90d72517347f74c2474dd3d (diff) | |
download | vim-git-b8d4905592fc26fcd09180d7d6bfefd899f2f6c6.tar.gz |
patch 7.4.1814v7.4.1814
Problem: A channel may be garbage collected while it's still being used by
a job. (James McCoy)
Solution: Mark the channel as used if the job is still used. Do the same
for channels that are still used.
Diffstat (limited to 'src')
-rw-r--r-- | src/channel.c | 43 | ||||
-rw-r--r-- | src/eval.c | 1 | ||||
-rw-r--r-- | src/proto/channel.pro | 1 | ||||
-rw-r--r-- | src/version.c | 2 |
4 files changed, 29 insertions, 18 deletions
diff --git a/src/channel.c b/src/channel.c index d8e55e7b2..4b7b6f72c 100644 --- a/src/channel.c +++ b/src/channel.c @@ -3553,28 +3553,15 @@ set_ref_in_channel(int copyID) { int abort = FALSE; channel_T *channel; - int part; + typval_T tv; for (channel = first_channel; channel != NULL; channel = channel->ch_next) - { - for (part = PART_SOCK; part < PART_IN; ++part) + if (channel_still_useful(channel)) { - jsonq_T *head = &channel->ch_part[part].ch_json_head; - jsonq_T *item = head->jq_next; - - while (item != NULL) - { - list_T *l = item->jq_value->vval.v_list; - - if (l->lv_copyID != copyID) - { - l->lv_copyID = copyID; - abort = abort || set_ref_in_list(l, copyID, NULL); - } - item = item->jq_next; - } + tv.v_type = VAR_CHANNEL; + tv.vval.v_channel = channel; + abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL); } - } return abort; } @@ -4092,6 +4079,26 @@ job_still_useful(job_T *job) && channel_still_useful(job->jv_channel))); } +/* + * Mark references in jobs that are still useful. + */ + int +set_ref_in_job(int copyID) +{ + int abort = FALSE; + job_T *job; + typval_T tv; + + for (job = first_job; job != NULL; job = job->jv_next) + if (job_still_useful(job)) + { + tv.v_type = VAR_JOB; + tv.vval.v_job = job; + abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL); + } + return abort; +} + void job_unref(job_T *job) { diff --git a/src/eval.c b/src/eval.c index 2b4f23012..fa2f839e3 100644 --- a/src/eval.c +++ b/src/eval.c @@ -7024,6 +7024,7 @@ garbage_collect(int testing) #ifdef FEAT_JOB_CHANNEL abort = abort || set_ref_in_channel(copyID); + abort = abort || set_ref_in_job(copyID); #endif #ifdef FEAT_NETBEANS_INTG abort = abort || set_ref_in_nb_channel(copyID); diff --git a/src/proto/channel.pro b/src/proto/channel.pro index d14337dc6..5e0bec54b 100644 --- a/src/proto/channel.pro +++ b/src/proto/channel.pro @@ -49,6 +49,7 @@ void clear_job_options(jobopt_T *opt); void free_job_options(jobopt_T *opt); int get_job_options(typval_T *tv, jobopt_T *opt, int supported); channel_T *get_channel_arg(typval_T *tv, int check_open, int reading, int part); +int set_ref_in_job(int copyID); void job_unref(job_T *job); int free_unused_jobs_contents(int copyID, int mask); void free_unused_jobs(int copyID, int mask); diff --git a/src/version.c b/src/version.c index 5a612d4fa..0d7847057 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 */ /**/ + 1814, +/**/ 1813, /**/ 1812, |