The current regex code may call mch_breakcheck which can process X events.
One of these events could be a remote_expr that makes its own call into the
regex engine. This usually crashes because the regex engine isn't
reentrant. This is probably also a problem for anything else that runs long
enough to make breakchecks and isn't reentrant.
This crash can usually be reproduced in linux by running vim with a
--servername argument and typing the command:
:call system("sleep 1 && vim --servername ".v:servername." --remote-expr
'substitute(string(range(5000)), \"a\", \"b\", \"g\")' &") | call
substitute(string(range(5000)), '\(,.*\)\@<!,', '', 'g')
The attached patch fixes the problem by preventing RealWaitForChar from
processing X events if it is called from mch_breakcheck.
Thanks,
James
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.
diff --git a/src/os_unix.c b/src/os_unix.c
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -177,9 +177,9 @@
static int WaitForChar __ARGS((long));
#if defined(__BEOS__) || defined(VMS)
-int RealWaitForChar __ARGS((int, long, int *));
+int RealWaitForChar __ARGS((int, long, int *, int));
#else
-static int RealWaitForChar __ARGS((int, long, int *));
+static int RealWaitForChar __ARGS((int, long, int *, int));
#endif
#ifdef FEAT_XCLIPBOARD
@@ -368,7 +368,7 @@
{
ignored = (int)write(1, (char *)s, len);
if (p_wd) /* Unix is too fast, slow down a bit more */
- RealWaitForChar(read_cmd_fd, p_wd, NULL);
+ RealWaitForChar(read_cmd_fd, p_wd, NULL, 1);
}
/*
@@ -4833,7 +4833,7 @@
* to some terminal (vt52?).
*/
++noread_cnt;
- while (RealWaitForChar(fromshell_fd, 10L, NULL))
+ while (RealWaitForChar(fromshell_fd, 10L, NULL, 1))
{
len = read_eintr(fromshell_fd, buffer
# ifdef FEAT_MBYTE
@@ -5114,7 +5114,7 @@
void
mch_breakcheck()
{
- if (curr_tmode == TMODE_RAW && RealWaitForChar(read_cmd_fd, 0L, NULL))
+ if (curr_tmode == TMODE_RAW && RealWaitForChar(read_cmd_fd, 0L, NULL, 0))
fill_input_buf(FALSE);
}
@@ -5171,9 +5171,9 @@
# endif
# ifdef FEAT_MOUSE_GPM
gpm_process_wanted = 0;
- avail = RealWaitForChar(read_cmd_fd, msec, &gpm_process_wanted);
+ avail = RealWaitForChar(read_cmd_fd, msec, &gpm_process_wanted, 1);
# else
- avail = RealWaitForChar(read_cmd_fd, msec, NULL);
+ avail = RealWaitForChar(read_cmd_fd, msec, NULL, 1);
# endif
if (!avail)
{
@@ -5195,7 +5195,7 @@
);
#else
- avail = RealWaitForChar(read_cmd_fd, msec, NULL);
+ avail = RealWaitForChar(read_cmd_fd, msec, NULL, 1);
#endif
return avail;
}
@@ -5214,10 +5214,11 @@
#else
static int
#endif
-RealWaitForChar(fd, msec, check_for_gpm)
+RealWaitForChar(fd, msec, check_for_gpm, allow_x)
int fd;
long msec;
int *check_for_gpm UNUSED;
+ int allow_x UNUSED; /* If 0, it is dangerous to handle X
events */
{
int ret;
#ifdef FEAT_NETBEANS_INTG
@@ -5310,13 +5311,16 @@
}
# endif
# ifdef FEAT_XCLIPBOARD
- may_restore_clipboard();
- if (xterm_Shell != (Widget)0)
+ if (allow_x)
{
- xterm_idx = nfd;
- fds[nfd].fd = ConnectionNumber(xterm_dpy);
- fds[nfd].events = POLLIN;
- nfd++;
+ may_restore_clipboard();
+ if (xterm_Shell != (Widget)0)
+ {
+ xterm_idx = nfd;
+ fds[nfd].fd = ConnectionNumber(xterm_dpy);
+ fds[nfd].events = POLLIN;
+ nfd++;
+ }
}
# endif
# ifdef FEAT_MOUSE_GPM
@@ -5366,12 +5370,15 @@
}
# endif
# ifdef FEAT_XCLIPBOARD
- if (xterm_Shell != (Widget)0 && (fds[xterm_idx].revents & POLLIN))
+ if (allow_x)
{
- xterm_update(); /* Maybe we should hand out clipboard */
- if (--ret == 0 && !input_available())
- /* Try again */
- finished = FALSE;
+ if (xterm_Shell != (Widget)0 && (fds[xterm_idx].revents & POLLIN))
+ {
+ xterm_update(); /* Maybe we should hand out clipboard */
+ if (--ret == 0 && !input_available())
+ /* Try again */
+ finished = FALSE;
+ }
}
# endif
# ifdef FEAT_MOUSE_GPM
@@ -5463,16 +5470,19 @@
}
# endif
# ifdef FEAT_XCLIPBOARD
- may_restore_clipboard();
- if (xterm_Shell != (Widget)0)
+ if (allow_x)
{
- FD_SET(ConnectionNumber(xterm_dpy), &rfds);
- if (maxfd < ConnectionNumber(xterm_dpy))
- maxfd = ConnectionNumber(xterm_dpy);
-
- /* An event may have already been read but not handled. In
- * particulary, XFlush may cause this. */
- xterm_update();
+ may_restore_clipboard();
+ if (xterm_Shell != (Widget)0)
+ {
+ FD_SET(ConnectionNumber(xterm_dpy), &rfds);
+ if (maxfd < ConnectionNumber(xterm_dpy))
+ maxfd = ConnectionNumber(xterm_dpy);
+
+ /* An event may have already been read but not handled. In
+ * particulary, XFlush may cause this. */
+ xterm_update();
+ }
}
# endif
# ifdef FEAT_MOUSE_GPM
@@ -5544,16 +5554,19 @@
}
# endif
# ifdef FEAT_XCLIPBOARD
- if (ret > 0 && xterm_Shell != (Widget)0
- && FD_ISSET(ConnectionNumber(xterm_dpy), &rfds))
+ if (allow_x)
{
- xterm_update(); /* Maybe we should hand out clipboard */
- /* continue looping when we only got the X event and the input
- * buffer is empty */
- if (--ret == 0 && !input_available())
+ if (ret > 0 && xterm_Shell != (Widget)0
+ && FD_ISSET(ConnectionNumber(xterm_dpy), &rfds))
{
- /* Try again */
- finished = FALSE;
+ xterm_update(); /* Maybe we should hand out clipboard */
+ /* continue looping when we only got the X event and the input
+ * buffer is empty */
+ if (--ret == 0 && !input_available())
+ {
+ /* Try again */
+ finished = FALSE;
+ }
}
}
# endif
diff --git a/src/proto/os_vms.pro b/src/proto/os_vms.pro
--- a/src/proto/os_vms.pro
+++ b/src/proto/os_vms.pro
@@ -12,5 +12,5 @@
int mch_expandpath __ARGS((garray_T *gap, char_u *path, int flags));
void *vms_fixfilename __ARGS((void *instring));
void vms_remove_version __ARGS((void *fname));
-int RealWaitForChar __ARGS((int fd, long msec, int *check_for_gpm));
+int RealWaitForChar __ARGS((int fd, long msec, int *check_for_gpm, int
allow_x));
/* vim: set ft=c : */
diff --git a/src/ui.c b/src/ui.c
--- a/src/ui.c
+++ b/src/ui.c
@@ -1801,7 +1801,7 @@
* On the BeBox version (for now), all input is secretly performed within
* beos_select() which is called from RealWaitForChar().
*/
- while (!vim_is_input_buf_full() && RealWaitForChar(read_cmd_fd, 0, NULL))
+ while (!vim_is_input_buf_full() && RealWaitForChar(read_cmd_fd, 0, NULL,
1))
;
len = inbufcount;
inbufcount = 0;