mirror of
https://github.com/vim/vim.git
synced 2025-09-27 04:14:06 -04:00
patch 7.4.866
Problem: Crash when changing the 'tags' option from a remote command. (Benjamin Fritz) Solution: Instead of executing messages immediately, use a queue, like for netbeans. (James Kolb)
This commit is contained in:
@@ -9033,11 +9033,11 @@ do_sleep(msec)
|
|||||||
{
|
{
|
||||||
ui_delay(msec - done > 1000L ? 1000L : msec - done, TRUE);
|
ui_delay(msec - done > 1000L ? 1000L : msec - done, TRUE);
|
||||||
ui_breakcheck();
|
ui_breakcheck();
|
||||||
#ifdef FEAT_NETBEANS_INTG
|
#ifdef MESSAGE_QUEUE
|
||||||
/* Process the netbeans messages that may have been received in the
|
/* Process the netbeans and clientserver messages that may have been
|
||||||
* call to ui_breakcheck() when the GUI is in use. This may occur when
|
* received in the call to ui_breakcheck() when the GUI is in use. This
|
||||||
* running a test case. */
|
* may occur when running a test case. */
|
||||||
netbeans_parse_messages();
|
parse_queued_messages();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3034,9 +3034,8 @@ inchar(buf, maxlen, wait_time, tb_change_cnt)
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
||||||
#if defined(FEAT_NETBEANS_INTG)
|
#ifdef MESSAGE_QUEUE
|
||||||
/* Process the queued netbeans messages. */
|
parse_queued_messages();
|
||||||
netbeans_parse_messages();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (got_int || (script_char = getc(scriptin[curscript])) < 0)
|
if (got_int || (script_char = getc(scriptin[curscript])) < 0)
|
||||||
|
@@ -650,7 +650,7 @@ property_event(GtkWidget *widget,
|
|||||||
xev.xproperty.atom = commProperty;
|
xev.xproperty.atom = commProperty;
|
||||||
xev.xproperty.window = commWindow;
|
xev.xproperty.window = commWindow;
|
||||||
xev.xproperty.state = PropertyNewValue;
|
xev.xproperty.state = PropertyNewValue;
|
||||||
serverEventProc(GDK_WINDOW_XDISPLAY(widget->window), &xev);
|
serverEventProc(GDK_WINDOW_XDISPLAY(widget->window), &xev, 0);
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -5476,9 +5476,8 @@ gui_mch_wait_for_chars(long wtime)
|
|||||||
focus = gui.in_focus;
|
focus = gui.in_focus;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(FEAT_NETBEANS_INTG)
|
#ifdef MESSAGE_QUEUE
|
||||||
/* Process any queued netbeans messages. */
|
parse_queued_messages();
|
||||||
netbeans_parse_messages();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -2016,9 +2016,8 @@ gui_mch_wait_for_chars(int wtime)
|
|||||||
s_need_activate = FALSE;
|
s_need_activate = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FEAT_NETBEANS_INTG
|
#ifdef MESSAGE_QUEUE
|
||||||
/* Process the queued netbeans messages. */
|
parse_queued_messages();
|
||||||
netbeans_parse_messages();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -2895,9 +2895,8 @@ gui_mch_wait_for_chars(wtime)
|
|||||||
focus = gui.in_focus;
|
focus = gui.in_focus;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(FEAT_NETBEANS_INTG)
|
#ifdef MESSAGE_QUEUE
|
||||||
/* Process any queued netbeans messages. */
|
parse_queued_messages();
|
||||||
netbeans_parse_messages();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3199,7 +3198,7 @@ gui_x11_send_event_handler(w, client_data, event, dum)
|
|||||||
if (e->type == PropertyNotify && e->window == commWindow
|
if (e->type == PropertyNotify && e->window == commWindow
|
||||||
&& e->atom == commProperty && e->state == PropertyNewValue)
|
&& e->atom == commProperty && e->state == PropertyNewValue)
|
||||||
{
|
{
|
||||||
serverEventProc(gui.dpy, event);
|
serverEventProc(gui.dpy, event, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
139
src/if_xcmdsrv.c
139
src/if_xcmdsrv.c
@@ -169,6 +169,19 @@ enum ServerReplyOp { SROP_Find, SROP_Add, SROP_Delete };
|
|||||||
|
|
||||||
typedef int (*EndCond) __ARGS((void *));
|
typedef int (*EndCond) __ARGS((void *));
|
||||||
|
|
||||||
|
struct x_cmdqueue
|
||||||
|
{
|
||||||
|
char_u *propInfo;
|
||||||
|
int len;
|
||||||
|
struct x_cmdqueue *next;
|
||||||
|
struct x_cmdqueue *prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct x_cmdqueue x_queue_T;
|
||||||
|
|
||||||
|
/* dummy node, header for circular queue */
|
||||||
|
static x_queue_T head = {NULL, 0, NULL, NULL};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Forward declarations for procedures defined later in this file:
|
* Forward declarations for procedures defined later in this file:
|
||||||
*/
|
*/
|
||||||
@@ -186,6 +199,8 @@ static struct ServerReply *ServerReplyFind __ARGS((Window w, enum ServerReplyOp
|
|||||||
static int AppendPropCarefully __ARGS((Display *display, Window window, Atom property, char_u *value, int length));
|
static int AppendPropCarefully __ARGS((Display *display, Window window, Atom property, char_u *value, int length));
|
||||||
static int x_error_check __ARGS((Display *dpy, XErrorEvent *error_event));
|
static int x_error_check __ARGS((Display *dpy, XErrorEvent *error_event));
|
||||||
static int IsSerialName __ARGS((char_u *name));
|
static int IsSerialName __ARGS((char_u *name));
|
||||||
|
static void save_in_queue __ARGS((char_u *buf, int len));
|
||||||
|
static void server_parse_message __ARGS((Display *dpy, char_u *propInfo, int numItems));
|
||||||
|
|
||||||
/* Private variables for the "server" functionality */
|
/* Private variables for the "server" functionality */
|
||||||
static Atom registryProperty = None;
|
static Atom registryProperty = None;
|
||||||
@@ -595,7 +610,7 @@ ServerWait(dpy, w, endCond, endData, localLoop, seconds)
|
|||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
while (XCheckWindowEvent(dpy, commWindow, PropertyChangeMask, &event))
|
while (XCheckWindowEvent(dpy, commWindow, PropertyChangeMask, &event))
|
||||||
serverEventProc(dpy, &event);
|
serverEventProc(dpy, &event, 1);
|
||||||
|
|
||||||
if (endCond(endData) != 0)
|
if (endCond(endData) != 0)
|
||||||
break;
|
break;
|
||||||
@@ -1127,22 +1142,25 @@ GetRegProp(dpy, regPropp, numItemsp, domsg)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This procedure is invoked by the various X event loops throughout Vims when
|
* This procedure is invoked by the various X event loops throughout Vims when
|
||||||
* a property changes on the communication window. This procedure reads the
|
* a property changes on the communication window. This procedure reads the
|
||||||
* property and handles command requests and responses.
|
* property and enqueues command requests and responses. If immediate is true,
|
||||||
|
* it runs the event immediatly instead of enqueuing it. Immediate can cause
|
||||||
|
* unintended behavior and should only be used for code that blocks for a
|
||||||
|
* response.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
serverEventProc(dpy, eventPtr)
|
serverEventProc(dpy, eventPtr, immediate)
|
||||||
Display *dpy;
|
Display *dpy;
|
||||||
XEvent *eventPtr; /* Information about event. */
|
XEvent *eventPtr; /* Information about event. */
|
||||||
|
int immediate; /* Run event immediately. Should mostly be 0. */
|
||||||
{
|
{
|
||||||
char_u *propInfo;
|
char_u *propInfo;
|
||||||
char_u *p;
|
int result, actualFormat;
|
||||||
int result, actualFormat, code;
|
|
||||||
long_u numItems, bytesAfter;
|
long_u numItems, bytesAfter;
|
||||||
Atom actualType;
|
Atom actualType;
|
||||||
char_u *tofree;
|
|
||||||
|
|
||||||
if (eventPtr != NULL)
|
if (eventPtr != NULL)
|
||||||
{
|
{
|
||||||
@@ -1168,6 +1186,87 @@ serverEventProc(dpy, eventPtr)
|
|||||||
XFree(propInfo);
|
XFree(propInfo);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (immediate)
|
||||||
|
server_parse_message(dpy, propInfo, numItems);
|
||||||
|
else
|
||||||
|
save_in_queue(propInfo, numItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Saves x clientserver commands in a queue so that they can be called when
|
||||||
|
* vim is idle.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
save_in_queue(propInfo, len)
|
||||||
|
char_u *propInfo;
|
||||||
|
int len;
|
||||||
|
{
|
||||||
|
x_queue_T *node;
|
||||||
|
|
||||||
|
node = (x_queue_T *)alloc(sizeof(x_queue_T));
|
||||||
|
if (node == NULL)
|
||||||
|
return; /* out of memory */
|
||||||
|
node->propInfo = propInfo;
|
||||||
|
node->len = len;
|
||||||
|
|
||||||
|
if (head.next == NULL) /* initialize circular queue */
|
||||||
|
{
|
||||||
|
head.next = &head;
|
||||||
|
head.prev = &head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* insert node at tail of queue */
|
||||||
|
node->next = &head;
|
||||||
|
node->prev = head.prev;
|
||||||
|
head.prev->next = node;
|
||||||
|
head.prev = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parses queued clientserver messages.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
server_parse_messages()
|
||||||
|
{
|
||||||
|
char_u *p;
|
||||||
|
x_queue_T *node;
|
||||||
|
|
||||||
|
if (!X_DISPLAY)
|
||||||
|
return; /* cannot happen? */
|
||||||
|
while (head.next != NULL && head.next != &head)
|
||||||
|
{
|
||||||
|
node = head.next;
|
||||||
|
server_parse_message(X_DISPLAY, node->propInfo, node->len);
|
||||||
|
head.next = node->next;
|
||||||
|
node->next->prev = node->prev;
|
||||||
|
vim_free(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns a non-zero value if there are clientserver messages waiting
|
||||||
|
* int the queue.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
server_waiting()
|
||||||
|
{
|
||||||
|
return head.next != NULL && head.next != &head;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prases a single clientserver message. A single message may contain multiple
|
||||||
|
* commands.
|
||||||
|
* "propInfo" will be freed.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
server_parse_message(dpy, propInfo, numItems)
|
||||||
|
Display *dpy;
|
||||||
|
char_u *propInfo; /* A string containing 0 or more X commands */
|
||||||
|
int numItems; /* The size of propInfo in bytes. */
|
||||||
|
{
|
||||||
|
char_u *p;
|
||||||
|
int code;
|
||||||
|
char_u *tofree;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Several commands and results could arrive in the property at
|
* Several commands and results could arrive in the property at
|
||||||
@@ -1248,16 +1347,16 @@ serverEventProc(dpy, eventPtr)
|
|||||||
if (script == NULL || name == NULL)
|
if (script == NULL || name == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (serverName != NULL && STRICMP(name, serverName) == 0)
|
if (serverName != NULL && STRICMP(name, serverName) == 0)
|
||||||
{
|
{
|
||||||
script = serverConvert(enc, script, &tofree);
|
script = serverConvert(enc, script, &tofree);
|
||||||
if (asKeys)
|
if (asKeys)
|
||||||
server_to_input_buf(script);
|
server_to_input_buf(script);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char_u *res;
|
char_u *res;
|
||||||
|
|
||||||
res = eval_client_expr_to_string(script);
|
res = eval_client_expr_to_string(script);
|
||||||
if (resWindow != None)
|
if (resWindow != None)
|
||||||
{
|
{
|
||||||
garray_T reply;
|
garray_T reply;
|
||||||
@@ -1290,10 +1389,10 @@ serverEventProc(dpy, eventPtr)
|
|||||||
reply.ga_data, reply.ga_len);
|
reply.ga_data, reply.ga_len);
|
||||||
ga_clear(&reply);
|
ga_clear(&reply);
|
||||||
}
|
}
|
||||||
vim_free(res);
|
vim_free(res);
|
||||||
}
|
}
|
||||||
vim_free(tofree);
|
vim_free(tofree);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (*p == 'r' && p[1] == 0)
|
else if (*p == 'r' && p[1] == 0)
|
||||||
{
|
{
|
||||||
|
@@ -321,3 +321,7 @@
|
|||||||
#else
|
#else
|
||||||
# define PLINES_NOFILL(x) plines(x)
|
# define PLINES_NOFILL(x) plines(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(FEAT_NETBEANS_INTG) || defined(FEAT_CLIENTSERVER)
|
||||||
|
# define MESSAGE_QUEUE
|
||||||
|
#endif
|
||||||
|
20
src/misc2.c
20
src/misc2.c
@@ -6328,3 +6328,23 @@ has_non_ascii(s)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(MESSAGE_QUEUE) || defined(PROTO)
|
||||||
|
/*
|
||||||
|
* Process messages that have been queued for netbeans or clientserver.
|
||||||
|
* These functions can call arbitrary vimscript and should only be called when
|
||||||
|
* it is safe to do so.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
parse_queued_messages()
|
||||||
|
{
|
||||||
|
# ifdef FEAT_NETBEANS_INTG
|
||||||
|
/* Process the queued netbeans messages. */
|
||||||
|
netbeans_parse_messages();
|
||||||
|
# endif
|
||||||
|
# ifdef FEAT_CLIENTSERVER
|
||||||
|
/* Process the queued clientserver messages. */
|
||||||
|
server_parse_messages();
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@@ -388,9 +388,8 @@ mch_inchar(buf, maxlen, wtime, tb_change_cnt)
|
|||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
#ifdef FEAT_NETBEANS_INTG
|
#ifdef MESSAGE_QUEUE
|
||||||
/* Process the queued netbeans messages. */
|
parse_queued_messages();
|
||||||
netbeans_parse_messages();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Check if window changed size while we were busy, perhaps the ":set
|
/* Check if window changed size while we were busy, perhaps the ":set
|
||||||
@@ -405,9 +404,8 @@ mch_inchar(buf, maxlen, wtime, tb_change_cnt)
|
|||||||
if (!do_resize) /* return if not interrupted by resize */
|
if (!do_resize) /* return if not interrupted by resize */
|
||||||
return 0;
|
return 0;
|
||||||
handle_resize();
|
handle_resize();
|
||||||
#ifdef FEAT_NETBEANS_INTG
|
#ifdef MESSAGE_QUEUE
|
||||||
/* Process the queued netbeans messages. */
|
parse_queued_messages();
|
||||||
netbeans_parse_messages();
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -439,9 +437,8 @@ mch_inchar(buf, maxlen, wtime, tb_change_cnt)
|
|||||||
while (do_resize) /* window changed size */
|
while (do_resize) /* window changed size */
|
||||||
handle_resize();
|
handle_resize();
|
||||||
|
|
||||||
#ifdef FEAT_NETBEANS_INTG
|
#ifdef MESSAGE_QUEUE
|
||||||
/* Process the queued netbeans messages. */
|
parse_queued_messages();
|
||||||
netbeans_parse_messages();
|
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* We want to be interrupted by the winch signal
|
* We want to be interrupted by the winch signal
|
||||||
@@ -5208,6 +5205,7 @@ WaitForChar(msec)
|
|||||||
* When a GUI is being used, this will not be used for input -- webb
|
* When a GUI is being used, this will not be used for input -- webb
|
||||||
* Returns also, when a request from Sniff is waiting -- toni.
|
* Returns also, when a request from Sniff is waiting -- toni.
|
||||||
* Or when a Linux GPM mouse event is waiting.
|
* Or when a Linux GPM mouse event is waiting.
|
||||||
|
* Or when a clientserver message is on the queue.
|
||||||
*/
|
*/
|
||||||
#if defined(__BEOS__)
|
#if defined(__BEOS__)
|
||||||
int
|
int
|
||||||
@@ -5601,6 +5599,11 @@ select_eintr:
|
|||||||
if (finished || msec == 0)
|
if (finished || msec == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
# ifdef FEAT_CLIENTSERVER
|
||||||
|
if (server_waiting())
|
||||||
|
break;
|
||||||
|
# endif
|
||||||
|
|
||||||
/* We're going to loop around again, find out for how long */
|
/* We're going to loop around again, find out for how long */
|
||||||
if (msec > 0)
|
if (msec > 0)
|
||||||
{
|
{
|
||||||
@@ -7106,31 +7109,31 @@ xterm_update()
|
|||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
XtInputMask mask = XtAppPending(app_context);
|
XtInputMask mask = XtAppPending(app_context);
|
||||||
|
|
||||||
if (mask == 0 || vim_is_input_buf_full())
|
if (mask == 0 || vim_is_input_buf_full())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (mask & XtIMXEvent)
|
if (mask & XtIMXEvent)
|
||||||
{
|
{
|
||||||
/* There is an event to process. */
|
/* There is an event to process. */
|
||||||
XtAppNextEvent(app_context, &event);
|
XtAppNextEvent(app_context, &event);
|
||||||
#ifdef FEAT_CLIENTSERVER
|
#ifdef FEAT_CLIENTSERVER
|
||||||
{
|
{
|
||||||
XPropertyEvent *e = (XPropertyEvent *)&event;
|
XPropertyEvent *e = (XPropertyEvent *)&event;
|
||||||
|
|
||||||
if (e->type == PropertyNotify && e->window == commWindow
|
if (e->type == PropertyNotify && e->window == commWindow
|
||||||
&& e->atom == commProperty && e->state == PropertyNewValue)
|
&& e->atom == commProperty && e->state == PropertyNewValue)
|
||||||
serverEventProc(xterm_dpy, &event);
|
serverEventProc(xterm_dpy, &event, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
XtDispatchEvent(&event);
|
XtDispatchEvent(&event);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* There is something else than an event to process. */
|
/* There is something else than an event to process. */
|
||||||
XtAppProcessEvent(app_context, mask);
|
XtAppProcessEvent(app_context, mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,5 +7,7 @@ Window serverStrToWin __ARGS((char_u *str));
|
|||||||
int serverSendReply __ARGS((char_u *name, char_u *str));
|
int serverSendReply __ARGS((char_u *name, char_u *str));
|
||||||
int serverReadReply __ARGS((Display *dpy, Window win, char_u **str, int localLoop));
|
int serverReadReply __ARGS((Display *dpy, Window win, char_u **str, int localLoop));
|
||||||
int serverPeekReply __ARGS((Display *dpy, Window win, char_u **str));
|
int serverPeekReply __ARGS((Display *dpy, Window win, char_u **str));
|
||||||
void serverEventProc __ARGS((Display *dpy, XEvent *eventPtr));
|
void serverEventProc __ARGS((Display *dpy, XEvent *eventPtr, int immediate));
|
||||||
|
void server_parse_messages __ARGS((void));
|
||||||
|
int server_waiting __ARGS((void));
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@@ -106,4 +106,5 @@ int put_bytes __ARGS((FILE *fd, long_u nr, int len));
|
|||||||
void put_time __ARGS((FILE *fd, time_t the_time));
|
void put_time __ARGS((FILE *fd, time_t the_time));
|
||||||
void time_to_bytes __ARGS((time_t the_time, char_u *buf));
|
void time_to_bytes __ARGS((time_t the_time, char_u *buf));
|
||||||
int has_non_ascii __ARGS((char_u *s));
|
int has_non_ascii __ARGS((char_u *s));
|
||||||
|
void parse_queued_messages __ARGS((void));
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@@ -741,6 +741,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
866,
|
||||||
/**/
|
/**/
|
||||||
865,
|
865,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user