# HG changeset patch # User Christian Brabandt # Date 1456482605 -3600 # Node ID 99a70c3b902fa7f50dc56714b6deca90d3f1501d # Parent c753d5773e64a1dbd93423344732191ef516fd04 commit https://github.com/vim/vim/commit/46c85439c966d7ed39fb3d711d4d6c61ac964647 Author: Bram Moolenaar 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. diff --git a/src/channel.c b/src/channel.c --- 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); diff --git a/src/eval.c b/src/eval.c --- 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 diff --git a/src/structs.h b/src/structs.h --- 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 */ }; diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -749,6 +749,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1422, +/**/ 1421, /**/ 1420,