summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-02-26 11:17:46 +0100
committerBram Moolenaar <Bram@vim.org>2016-02-26 11:17:46 +0100
commit46c85439c966d7ed39fb3d711d4d6c61ac964647 (patch)
tree9c9530e6f4472e240d23806de7728d2a77b1d766
parentc8dcbb12c5d7f3eb0c334daebb4475bb015b91e7 (diff)
patch 7.4.1422v7.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.
-rw-r--r--src/channel.c26
-rw-r--r--src/eval.c14
-rw-r--r--src/structs.h2
-rw-r--r--src/version.c2
4 files changed, 31 insertions, 13 deletions
diff --git a/src/channel.c b/src/channel.c
index 4a2b20c442..03dbdc3017 100644
--- 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 part, char *func)
* -> 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 part, char *func)
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
index 0db6cfac53..f9e85178bf 100644
--- 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, typval_T *rettv UNUSED)
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
index 5f70c732b6..c0339de81c 100644
--- 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
index 42200012a4..08c8c1a8ed 100644
--- 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,