Merge remote-tracking branch 'vim/master'

This commit is contained in:
Kazuki Sakamoto
2016-05-09 19:45:00 -07:00
5 changed files with 127 additions and 18 deletions
+3
View File
@@ -680,6 +680,9 @@ free_buffer(buf_T *buf)
#ifdef FEAT_RUBY
ruby_buffer_free(buf);
#endif
#ifdef FEAT_JOB_CHANNEL
channel_buffer_free(buf);
#endif
#ifdef FEAT_AUTOCMD
aubuflocal_remove(buf);
if (autocmd_busy)
+110 -18
View File
@@ -61,6 +61,11 @@ static void channel_read(channel_T *channel, int part, char *func);
/* Whether a redraw is needed for appending a line to a buffer. */
static int channel_need_redraw = FALSE;
/* Whether we are inside channel_parse_messages() or another situation where it
* is safe to invoke callbacks. */
static int safe_to_invoke_callback = 0;
static char *part_names[] = {"sock", "out", "err", "in"};
#ifdef WIN32
static int
@@ -408,8 +413,15 @@ channel_free(channel_T *channel)
{
if (!in_free_unref_items)
{
channel_free_contents(channel);
channel_free_channel(channel);
if (safe_to_invoke_callback == 0)
{
channel->ch_to_be_freed = TRUE;
}
else
{
channel_free_contents(channel);
channel_free_channel(channel);
}
}
}
@@ -449,6 +461,10 @@ free_unused_channels_contents(int copyID, int mask)
int did_free = FALSE;
channel_T *ch;
/* This is invoked from the garbage collector, which only runs at a safe
* point. */
++safe_to_invoke_callback;
for (ch = first_channel; ch != NULL; ch = ch->ch_next)
if (!channel_still_useful(ch)
&& (ch->ch_copyID & mask) != (copyID & mask))
@@ -458,6 +474,8 @@ free_unused_channels_contents(int copyID, int mask)
channel_free_contents(ch);
did_free = TRUE;
}
--safe_to_invoke_callback;
return did_free;
}
@@ -1073,6 +1091,7 @@ channel_set_job(channel_T *channel, job_T *job, jobopt_T *options)
/*
* Find a buffer matching "name" or create a new one.
* Returns NULL if there is something very wrong (error already reported).
*/
static buf_T *
find_buffer(char_u *name, int err)
@@ -1086,6 +1105,8 @@ find_buffer(char_u *name, int err)
{
buf = buflist_new(name == NULL || *name == NUL ? NULL : name,
NULL, (linenr_T)0, BLN_LISTED);
if (buf == NULL)
return NULL;
buf_copy_options(buf, BCO_ENTER);
curbuf = buf;
#ifdef FEAT_QUICKFIX
@@ -1192,37 +1213,54 @@ channel_set_options(channel_T *channel, jobopt_T *opt)
if ((opt->jo_set & JO_OUT_IO) && opt->jo_io[PART_OUT] == JIO_BUFFER)
{
buf_T *buf;
/* writing output to a buffer. Default mode is NL. */
if (!(opt->jo_set & JO_OUT_MODE))
channel->ch_part[PART_OUT].ch_mode = MODE_NL;
if (opt->jo_set & JO_OUT_BUF)
channel->ch_part[PART_OUT].ch_buffer =
buflist_findnr(opt->jo_io_buf[PART_OUT]);
{
buf = buflist_findnr(opt->jo_io_buf[PART_OUT]);
if (buf == NULL)
EMSGN(_(e_nobufnr), (long)opt->jo_io_buf[PART_OUT]);
}
else
channel->ch_part[PART_OUT].ch_buffer =
find_buffer(opt->jo_io_name[PART_OUT], FALSE);
ch_logs(channel, "writing out to buffer '%s'",
(char *)channel->ch_part[PART_OUT].ch_buffer->b_ffname);
{
buf = find_buffer(opt->jo_io_name[PART_OUT], FALSE);
}
if (buf != NULL)
{
ch_logs(channel, "writing out to buffer '%s'",
(char *)buf->b_ffname);
channel->ch_part[PART_OUT].ch_buffer = buf;
}
}
if ((opt->jo_set & JO_ERR_IO) && (opt->jo_io[PART_ERR] == JIO_BUFFER
|| (opt->jo_io[PART_ERR] == JIO_OUT && (opt->jo_set & JO_OUT_IO)
&& opt->jo_io[PART_OUT] == JIO_BUFFER)))
{
buf_T *buf;
/* writing err to a buffer. Default mode is NL. */
if (!(opt->jo_set & JO_ERR_MODE))
channel->ch_part[PART_ERR].ch_mode = MODE_NL;
if (opt->jo_io[PART_ERR] == JIO_OUT)
channel->ch_part[PART_ERR].ch_buffer =
channel->ch_part[PART_OUT].ch_buffer;
buf = channel->ch_part[PART_OUT].ch_buffer;
else if (opt->jo_set & JO_ERR_BUF)
channel->ch_part[PART_ERR].ch_buffer =
buflist_findnr(opt->jo_io_buf[PART_ERR]);
{
buf = buflist_findnr(opt->jo_io_buf[PART_ERR]);
if (buf == NULL)
EMSGN(_(e_nobufnr), (long)opt->jo_io_buf[PART_ERR]);
}
else
channel->ch_part[PART_ERR].ch_buffer =
find_buffer(opt->jo_io_name[PART_ERR], TRUE);
ch_logs(channel, "writing err to buffer '%s'",
(char *)channel->ch_part[PART_ERR].ch_buffer->b_ffname);
buf = find_buffer(opt->jo_io_name[PART_ERR], TRUE);
if (buf != NULL)
{
ch_logs(channel, "writing err to buffer '%s'",
(char *)buf->b_ffname);
channel->ch_part[PART_ERR].ch_buffer = buf;
}
}
channel->ch_part[PART_OUT].ch_io = opt->jo_io[PART_OUT];
@@ -1392,6 +1430,29 @@ channel_write_in(channel_T *channel)
buf->b_ml.ml_line_count - lnum + 1);
}
/*
* Handle buffer "buf" beeing freed, remove it from any channels.
*/
void
channel_buffer_free(buf_T *buf)
{
channel_T *channel;
int part;
for (channel = first_channel; channel != NULL; channel = channel->ch_next)
for (part = PART_SOCK; part <= PART_IN; ++part)
{
chanpart_T *ch_part = &channel->ch_part[part];
if (ch_part->ch_buffer == buf)
{
ch_logs(channel, "%s buffer has been wiped out",
part_names[part]);
ch_part->ch_buffer = NULL;
}
}
}
/*
* Write any lines waiting to be written to a channel.
*/
@@ -1471,6 +1532,9 @@ invoke_callback(channel_T *channel, char_u *callback, partial_T *partial,
typval_T rettv;
int dummy;
if (safe_to_invoke_callback == 0)
EMSG("INTERNAL: Invoking callback when it is not safe");
argv[0].v_type = VAR_CHANNEL;
argv[0].vval.v_channel = channel;
@@ -2803,7 +2867,8 @@ channel_wait(channel_T *channel, sock_T fd, int timeout)
channel_close_on_error(channel_T *channel, char *func)
{
/* Do not call emsg(), most likely the other end just exited. */
ch_errors(channel, "%s(): Cannot read from channel", func);
ch_errors(channel, "%s(): Cannot read from channel, will close it soon",
func);
/* Queue a "DETACH" netbeans message in the command queue in order to
* terminate the netbeans session later. Do not end the session here
@@ -2821,7 +2886,15 @@ channel_close_on_error(channel_T *channel, char *func)
(int)STRLEN(DETACH_MSG_RAW), FALSE, "PUT ");
/* When reading from stdout is not possible, assume the other side has
* died. */
* died. Don't close the channel right away, it may be the wrong moment
* to invoke callbacks. */
channel->ch_to_be_closed = TRUE;
}
static void
channel_close_now(channel_T *channel)
{
ch_log(channel, "Closing channel because of previous read error");
channel_close(channel, TRUE);
if (channel->ch_nb_close_cb != NULL)
(*channel->ch_nb_close_cb)();
@@ -3531,6 +3604,8 @@ channel_parse_messages(void)
int r;
int part = PART_SOCK;
++safe_to_invoke_callback;
/* Only do this message when another message was given, otherwise we get
* lots of them. */
if (did_log_msg)
@@ -3540,6 +3615,21 @@ channel_parse_messages(void)
}
while (channel != NULL)
{
if (channel->ch_to_be_closed)
{
channel->ch_to_be_closed = FALSE;
channel_close_now(channel);
/* channel may have been freed, start over */
channel = first_channel;
continue;
}
if (channel->ch_to_be_freed)
{
channel_free(channel);
/* channel has been freed, start over */
channel = first_channel;
continue;
}
if (channel->ch_refcount == 0 && !channel_still_useful(channel))
{
/* channel is no longer useful, free it */
@@ -3580,6 +3670,8 @@ channel_parse_messages(void)
redraw_after_callback();
}
--safe_to_invoke_callback;
return ret;
}
+1
View File
@@ -14,6 +14,7 @@ void channel_set_pipes(channel_T *channel, sock_T in, sock_T out, sock_T err);
void channel_set_job(channel_T *channel, job_T *job, jobopt_T *options);
void channel_set_options(channel_T *channel, jobopt_T *opt);
void channel_set_req_callback(channel_T *channel, int part, char_u *callback, partial_T *partial, int id);
void channel_buffer_free(buf_T *buf);
void channel_write_any_lines(void);
void channel_write_new_lines(buf_T *buf);
char_u *channel_get(channel_T *channel, int part);
+5
View File
@@ -1419,6 +1419,11 @@ struct channel_S {
char *ch_hostname; /* only for socket, allocated */
int ch_port; /* only for socket */
int ch_to_be_closed; /* When TRUE reading or writing failed and
* the channel must be closed when it's safe
* to invoke callbacks. */
int ch_to_be_freed; /* When TRUE channel must be freed when it's
* safe to invoke callbacks. */
int ch_error; /* When TRUE an error was reported. Avoids
* giving pages full of error messages when
* the other side has exited, only mention the
+8
View File
@@ -768,6 +768,14 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1829,
/**/
1828,
/**/
1827,
/**/
1826,
/**/
1825,
/**/