1
0
forked from aniani/vim

patch 7.4.1827

Problem:    No error when invoking a callback when it's not safe.
Solution:   Add an error message.  Avoid the error when freeing a channel.
This commit is contained in:
Bram Moolenaar
2016-05-09 17:58:04 +02:00
parent cf7ff70ca7
commit fb6ffc732e
3 changed files with 36 additions and 2 deletions

View File

@@ -59,6 +59,9 @@ 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;
#ifdef WIN32
static int
@@ -402,10 +405,17 @@ channel_free_channel(channel_T *channel)
channel_free(channel_T *channel)
{
if (!in_free_unref_items)
{
if (safe_to_invoke_callback == 0)
{
channel->ch_to_be_freed = TRUE;
}
else
{
channel_free_contents(channel);
channel_free_channel(channel);
}
}
}
/*
@@ -444,6 +454,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))
@@ -453,6 +467,8 @@ free_unused_channels_contents(int copyID, int mask)
channel_free_contents(ch);
did_free = TRUE;
}
--safe_to_invoke_callback;
return did_free;
}
@@ -1450,6 +1466,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;
@@ -3515,6 +3534,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)
@@ -3532,6 +3553,13 @@ channel_parse_messages(void)
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 */
@@ -3572,6 +3600,8 @@ channel_parse_messages(void)
redraw_after_callback();
}
--safe_to_invoke_callback;
return ret;
}

View File

@@ -1419,6 +1419,8 @@ struct channel_S {
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

View File

@@ -753,6 +753,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1827,
/**/
1826,
/**/