1
0
forked from aniani/vim

patch 8.0.1761: job in terminal window with no output channel is killed

Problem:    Job in terminal window with no output channel is killed.
Solution:   Keep the job running when the input is a tty. (Ozaki Kiichi,
            closes #2734)
This commit is contained in:
Bram Moolenaar
2018-04-24 20:54:07 +02:00
parent 4994373c5d
commit 4e9d443a25
4 changed files with 59 additions and 15 deletions

View File

@@ -344,6 +344,15 @@ channel_still_useful(channel_T *channel)
&& has_err_msg);
}
/*
* Return TRUE if "channel" is closeable (i.e. all readable fds are closed).
*/
static int
channel_can_close(channel_T *channel)
{
return channel->ch_to_be_closed == 0;
}
/*
* Close a channel and free all its resources.
*/
@@ -892,7 +901,7 @@ channel_open(
channel->ch_nb_close_cb = nb_close_cb;
channel->ch_hostname = (char *)vim_strsave((char_u *)hostname);
channel->ch_port = port_in;
channel->ch_to_be_closed |= (1 << PART_SOCK);
channel->ch_to_be_closed |= (1U << PART_SOCK);
#ifdef FEAT_GUI
channel_gui_register_one(channel, PART_SOCK);
@@ -988,7 +997,8 @@ ch_close_part(channel_T *channel, ch_part_T part)
}
*fd = INVALID_FD;
channel->ch_to_be_closed &= ~(1 << part);
/* channel is closed, may want to end the job if it was the last */
channel->ch_to_be_closed &= ~(1U << part);
}
}
@@ -999,6 +1009,12 @@ channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err)
{
ch_close_part(channel, PART_IN);
channel->CH_IN_FD = in;
# if defined(UNIX)
/* Do not end the job when all output channels are closed, wait until
* the job ended. */
if (isatty(in))
channel->ch_to_be_closed |= (1U << PART_IN);
# endif
}
if (out != INVALID_FD)
{
@@ -1007,7 +1023,7 @@ channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err)
# endif
ch_close_part(channel, PART_OUT);
channel->CH_OUT_FD = out;
channel->ch_to_be_closed |= (1 << PART_OUT);
channel->ch_to_be_closed |= (1U << PART_OUT);
# if defined(FEAT_GUI)
channel_gui_register_one(channel, PART_OUT);
# endif
@@ -1019,7 +1035,7 @@ channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err)
# endif
ch_close_part(channel, PART_ERR);
channel->CH_ERR_FD = err;
channel->ch_to_be_closed |= (1 << PART_ERR);
channel->ch_to_be_closed |= (1U << PART_ERR);
# if defined(FEAT_GUI)
channel_gui_register_one(channel, PART_ERR);
# endif
@@ -4200,9 +4216,9 @@ channel_parse_messages(void)
}
while (channel != NULL)
{
if (channel->ch_to_be_closed == 0)
if (channel_can_close(channel))
{
channel->ch_to_be_closed = (1 << PART_COUNT);
channel->ch_to_be_closed = (1U << PART_COUNT);
channel_close_now(channel);
/* channel may have been freed, start over */
channel = first_channel;
@@ -5079,6 +5095,15 @@ job_channel_still_useful(job_T *job)
return job->jv_channel != NULL && channel_still_useful(job->jv_channel);
}
/*
* Return TRUE if the channel of "job" is closeable.
*/
static int
job_channel_can_close(job_T *job)
{
return job->jv_channel != NULL && channel_can_close(job->jv_channel);
}
/*
* 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, an exit callback
@@ -5209,6 +5234,10 @@ job_cleanup(job_T *job)
/* Ready to cleanup the job. */
job->jv_status = JOB_FINISHED;
/* When only channel-in is kept open, close explicitly. */
if (job->jv_channel != NULL)
ch_close_part(job->jv_channel, PART_IN);
if (job->jv_exit_cb != NULL)
{
typval_T argv[3];
@@ -5413,8 +5442,9 @@ has_pending_job(void)
for (job = first_job; job != NULL; job = job->jv_next)
/* Only should check if the channel has been closed, if the channel is
* open the job won't exit. */
if (job->jv_status == JOB_STARTED && job->jv_exit_cb != NULL
&& !job_channel_still_useful(job))
if ((job->jv_status == JOB_STARTED && !job_channel_still_useful(job))
|| (job->jv_status == JOB_FINISHED
&& job_channel_can_close(job)))
return TRUE;
return FALSE;
}