&& 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.
*/
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);
}
*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);
}
}
{
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)
{
# 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
# 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
}
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;
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
/* 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];
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;
}
close(fd_err[1]);
if (channel != NULL)
{
- channel_set_pipes(channel,
- use_file_for_in || use_null_for_in
- ? INVALID_FD : fd_in[1] < 0 ? pty_master_fd : fd_in[1],
- use_file_for_out || use_null_for_out
- ? INVALID_FD : fd_out[0] < 0 ? pty_master_fd : fd_out[0],
- use_out_for_err || use_file_for_err || use_null_for_err
- ? INVALID_FD : fd_err[0] < 0 ? pty_master_fd : fd_err[0]);
+ int in_fd = use_file_for_in || use_null_for_in
+ ? INVALID_FD : fd_in[1] < 0 ? pty_master_fd : fd_in[1];
+ int out_fd = use_file_for_out || use_null_for_out
+ ? INVALID_FD : fd_out[0] < 0 ? pty_master_fd : fd_out[0];
+ int err_fd = use_out_for_err || use_file_for_err || use_null_for_err
+ ? INVALID_FD : fd_err[0] < 0 ? pty_master_fd : fd_err[0];
+
+ channel_set_pipes(channel, in_fd, out_fd, err_fd);
channel_set_job(channel, job, options);
}
else