Mercurial > vim
changeset 8259:99a70c3b902f v7.4.1422
commit https://github.com/vim/vim/commit/46c85439c966d7ed39fb3d711d4d6c61ac964647
Author: Bram Moolenaar <Bram@vim.org>
Date: Fri Feb 26 11:17:46 2016 +0100
patch 7.4.1422
Problem: Error when reading fails uses wrong errno. Keeping channel open
after job stops results in test failing.
Solution: Move the error up. Add ch_job_killed.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Fri, 26 Feb 2016 11:30:05 +0100 |
parents | c753d5773e64 |
children | a61da15cb3f3 |
files | src/channel.c src/eval.c src/structs.h src/version.c |
diffstat | 4 files changed, 31 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/src/channel.c +++ b/src/channel.c @@ -307,11 +307,14 @@ add_channel(void) } /* - * Return TRUE if "channel" has a callback. + * Return TRUE if "channel" has a callback and the associated job wasn't + * killed. */ static int -channel_has_callback(channel_T *channel) +channel_still_useful(channel_T *channel) { + if (channel->ch_job_killed && channel->ch_job == NULL) + return FALSE; return channel->ch_callback != NULL #ifdef CHANNEL_PIPES || channel->ch_part[PART_OUT].ch_callback != NULL @@ -322,12 +325,13 @@ channel_has_callback(channel_T *channel) /* * Close a channel and free all its resources if there is no further action - * possible, there is no callback to be invoked. + * possible, there is no callback to be invoked or the associated job was + * killed. */ void channel_may_free(channel_T *channel) { - if (!channel_has_callback(channel)) + if (!channel_still_useful(channel)) channel_free(channel); } @@ -1774,6 +1778,12 @@ channel_read(channel_T *channel, int par * -> channel_read() */ ch_errors(channel, "%s(): Cannot read", func); + if (len < 0) + { + ch_error(channel, "channel_read(): cannot read from channel"); + PERROR(_("E896: read from channel")); + } + msg = channel->ch_part[part].ch_mode == MODE_RAW || channel->ch_part[part].ch_mode == MODE_NL ? DETACH_MSG_RAW : DETACH_MSG_JSON; @@ -1785,12 +1795,6 @@ channel_read(channel_T *channel, int par channel_close(channel, TRUE); if (channel->ch_nb_close_cb != NULL) (*channel->ch_nb_close_cb)(); - - if (len < 0) - { - ch_error(channel, "channel_read(): cannot read from channel"); - PERROR(_("E896: read from channel")); - } } #if defined(CH_HAS_GUI) && defined(FEAT_GUI_GTK) @@ -2174,7 +2178,7 @@ channel_parse_messages(void) while (channel != NULL) { - if (channel->ch_refcount == 0 && !channel_has_callback(channel)) + if (channel->ch_refcount == 0 && !channel_still_useful(channel)) { /* channel is no longer useful, free it */ channel_free(channel);
--- a/src/eval.c +++ b/src/eval.c @@ -7770,8 +7770,11 @@ job_free(job_T *job) # ifdef FEAT_CHANNEL if (job->jv_channel != NULL) { - /* The channel doesn't count as a references for the job, we need to - * NULL the reference when the job is freed. */ + /* The link from the channel to the job doesn't count as a reference, + * thus don't decrement the refcount of the job. The reference from + * the job to the channel does count the refrence, decrement it and + * NULL the reference. We don't set ch_job_killed, unreferencing the + * job doesn't mean it stops running. */ job->jv_channel->ch_job = NULL; channel_unref(job->jv_channel); } @@ -15161,7 +15164,14 @@ f_job_stop(typval_T *argvars UNUSED, typ if (mch_stop_job(job, arg) == FAIL) rettv->vval.v_number = 0; else + { rettv->vval.v_number = 1; + /* Assume that "hup" does not kill the job. */ + if (job->jv_channel != NULL && STRCMP(arg, "hup") != 0) + job->jv_channel->ch_job_killed = TRUE; + } + /* We don't try freeing the job, obviously the caller still has a + * reference to it. */ } } #endif
--- a/src/structs.h +++ b/src/structs.h @@ -1373,6 +1373,8 @@ struct channel_S { job_T *ch_job; /* Job that uses this channel; this does not * count as a reference to avoid a circular * reference. */ + int ch_job_killed; /* TRUE when there was a job and it was killed + * or we know it died. */ int ch_refcount; /* reference count */ };