mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 7.4.1886
Problem: When waiting for a character is interrupted by receiving channel data and the first character of a mapping was typed, the mapping times out. (Ramel Eshed) Solution: When dealing with channel data don't return from mch_inchar().
This commit is contained in:
parent
1aa07bdead
commit
cda7764d8e
@ -129,6 +129,7 @@ static int vgetorpeek(int);
|
|||||||
static void map_free(mapblock_T **);
|
static void map_free(mapblock_T **);
|
||||||
static void validate_maphash(void);
|
static void validate_maphash(void);
|
||||||
static void showmap(mapblock_T *mp, int local);
|
static void showmap(mapblock_T *mp, int local);
|
||||||
|
static int inchar(char_u *buf, int maxlen, long wait_time, int tb_change_cnt);
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
static char_u *eval_map_expr(char_u *str, int c);
|
static char_u *eval_map_expr(char_u *str, int c);
|
||||||
#endif
|
#endif
|
||||||
@ -2941,7 +2942,7 @@ vgetorpeek(int advance)
|
|||||||
* Return the number of obtained characters.
|
* Return the number of obtained characters.
|
||||||
* Return -1 when end of input script reached.
|
* Return -1 when end of input script reached.
|
||||||
*/
|
*/
|
||||||
int
|
static int
|
||||||
inchar(
|
inchar(
|
||||||
char_u *buf,
|
char_u *buf,
|
||||||
int maxlen,
|
int maxlen,
|
||||||
|
101
src/os_unix.c
101
src/os_unix.c
@ -175,12 +175,12 @@ typedef int waitstatus;
|
|||||||
#endif
|
#endif
|
||||||
static pid_t wait4pid(pid_t, waitstatus *);
|
static pid_t wait4pid(pid_t, waitstatus *);
|
||||||
|
|
||||||
static int WaitForChar(long);
|
static int WaitForChar(long msec, int *interrupted);
|
||||||
static int WaitForCharOrMouse(long, int *break_loop);
|
static int WaitForCharOrMouse(long msec, int *interrupted);
|
||||||
#if defined(__BEOS__) || defined(VMS)
|
#if defined(__BEOS__) || defined(VMS)
|
||||||
int RealWaitForChar(int, long, int *, int *break_loop);
|
int RealWaitForChar(int, long, int *, int *interrupted);
|
||||||
#else
|
#else
|
||||||
static int RealWaitForChar(int, long, int *, int *break_loop);
|
static int RealWaitForChar(int, long, int *, int *interrupted);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef FEAT_XCLIPBOARD
|
#ifdef FEAT_XCLIPBOARD
|
||||||
@ -385,6 +385,7 @@ mch_inchar(
|
|||||||
int tb_change_cnt)
|
int tb_change_cnt)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
int interrupted = FALSE;
|
||||||
|
|
||||||
#ifdef MESSAGE_QUEUE
|
#ifdef MESSAGE_QUEUE
|
||||||
parse_queued_messages();
|
parse_queued_messages();
|
||||||
@ -397,20 +398,31 @@ mch_inchar(
|
|||||||
|
|
||||||
if (wtime >= 0)
|
if (wtime >= 0)
|
||||||
{
|
{
|
||||||
while (!WaitForChar(wtime)) /* no character available */
|
/* TODO: when looping reduce wtime by the elapsed time. */
|
||||||
|
while (!WaitForChar(wtime, &interrupted))
|
||||||
{
|
{
|
||||||
|
/* no character available */
|
||||||
if (do_resize)
|
if (do_resize)
|
||||||
|
{
|
||||||
handle_resize();
|
handle_resize();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
#ifdef FEAT_CLIENTSERVER
|
#ifdef FEAT_CLIENTSERVER
|
||||||
else if (!server_waiting())
|
if (server_waiting())
|
||||||
#else
|
{
|
||||||
else
|
parse_queued_messages();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef MESSAGE_QUEUE
|
||||||
|
if (interrupted)
|
||||||
|
{
|
||||||
|
parse_queued_messages();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
/* return if not interrupted by resize or server */
|
/* return if not interrupted by resize or server */
|
||||||
return 0;
|
return 0;
|
||||||
#ifdef MESSAGE_QUEUE
|
|
||||||
parse_queued_messages();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else /* wtime == -1 */
|
else /* wtime == -1 */
|
||||||
@ -420,8 +432,9 @@ mch_inchar(
|
|||||||
* flush all the swap files to disk.
|
* flush all the swap files to disk.
|
||||||
* Also done when interrupted by SIGWINCH.
|
* Also done when interrupted by SIGWINCH.
|
||||||
*/
|
*/
|
||||||
if (!WaitForChar(p_ut))
|
if (!WaitForChar(p_ut, &interrupted))
|
||||||
{
|
{
|
||||||
|
/* TODO: if interrupted is set loop to wait the remaining time. */
|
||||||
#ifdef FEAT_AUTOCMD
|
#ifdef FEAT_AUTOCMD
|
||||||
if (trigger_cursorhold() && maxlen >= 3
|
if (trigger_cursorhold() && maxlen >= 3
|
||||||
&& !typebuf_changed(tb_change_cnt))
|
&& !typebuf_changed(tb_change_cnt))
|
||||||
@ -436,7 +449,8 @@ mch_inchar(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) /* repeat until we got a character */
|
/* repeat until we got a character */
|
||||||
|
for (;;)
|
||||||
{
|
{
|
||||||
long wtime_now = -1L;
|
long wtime_now = -1L;
|
||||||
|
|
||||||
@ -462,10 +476,17 @@ mch_inchar(
|
|||||||
* We want to be interrupted by the winch signal
|
* We want to be interrupted by the winch signal
|
||||||
* or by an event on the monitored file descriptors.
|
* or by an event on the monitored file descriptors.
|
||||||
*/
|
*/
|
||||||
if (!WaitForChar(wtime_now))
|
if (!WaitForChar(wtime_now, &interrupted))
|
||||||
{
|
{
|
||||||
if (do_resize) /* interrupted by SIGWINCH signal */
|
if (do_resize) /* interrupted by SIGWINCH signal */
|
||||||
handle_resize();
|
continue;
|
||||||
|
#ifdef MESSAGE_QUEUE
|
||||||
|
if (interrupted || wtime_now > 0)
|
||||||
|
{
|
||||||
|
parse_queued_messages();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,10 +503,8 @@ mch_inchar(
|
|||||||
*/
|
*/
|
||||||
len = read_from_input_buf(buf, (long)maxlen);
|
len = read_from_input_buf(buf, (long)maxlen);
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
{
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -501,7 +520,7 @@ handle_resize(void)
|
|||||||
int
|
int
|
||||||
mch_char_avail(void)
|
mch_char_avail(void)
|
||||||
{
|
{
|
||||||
return WaitForChar(0L);
|
return WaitForChar(0L, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_TOTAL_MEM) || defined(PROTO)
|
#if defined(HAVE_TOTAL_MEM) || defined(PROTO)
|
||||||
@ -691,7 +710,7 @@ mch_delay(long msec, int ignoreinput)
|
|||||||
in_mch_delay = FALSE;
|
in_mch_delay = FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
WaitForChar(msec);
|
WaitForChar(msec, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_STACK_LIMIT) \
|
#if defined(HAVE_STACK_LIMIT) \
|
||||||
@ -5229,6 +5248,10 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
|
|||||||
|
|
||||||
if (stderr_works)
|
if (stderr_works)
|
||||||
perror("executing job failed");
|
perror("executing job failed");
|
||||||
|
#ifdef EXITFREE
|
||||||
|
/* calling free_all_mem() here causes problems. Ignore valgrind
|
||||||
|
* reporting possibly leaked memory. */
|
||||||
|
#endif
|
||||||
_exit(EXEC_FAILED); /* exec failed, return failure code */
|
_exit(EXEC_FAILED); /* exec failed, return failure code */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5376,16 +5399,17 @@ mch_breakcheck(void)
|
|||||||
* from inbuf[].
|
* from inbuf[].
|
||||||
* "msec" == -1 will block forever.
|
* "msec" == -1 will block forever.
|
||||||
* Invokes timer callbacks when needed.
|
* Invokes timer callbacks when needed.
|
||||||
* When a GUI is being used, this will never get called -- webb
|
* "interrupted" (if not NULL) is set to TRUE when no character is available
|
||||||
|
* but something else needs to be done.
|
||||||
* Returns TRUE when a character is available.
|
* Returns TRUE when a character is available.
|
||||||
|
* When a GUI is being used, this will never get called -- webb
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
WaitForChar(long msec)
|
WaitForChar(long msec, int *interrupted)
|
||||||
{
|
{
|
||||||
#ifdef FEAT_TIMERS
|
#ifdef FEAT_TIMERS
|
||||||
long due_time;
|
long due_time;
|
||||||
long remaining = msec;
|
long remaining = msec;
|
||||||
int break_loop = FALSE;
|
|
||||||
int tb_change_cnt = typebuf.tb_change_cnt;
|
int tb_change_cnt = typebuf.tb_change_cnt;
|
||||||
|
|
||||||
/* When waiting very briefly don't trigger timers. */
|
/* When waiting very briefly don't trigger timers. */
|
||||||
@ -5404,9 +5428,9 @@ WaitForChar(long msec)
|
|||||||
}
|
}
|
||||||
if (due_time <= 0 || (msec > 0 && due_time > remaining))
|
if (due_time <= 0 || (msec > 0 && due_time > remaining))
|
||||||
due_time = remaining;
|
due_time = remaining;
|
||||||
if (WaitForCharOrMouse(due_time, &break_loop))
|
if (WaitForCharOrMouse(due_time, interrupted))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
if (break_loop)
|
if (interrupted != NULL && *interrupted)
|
||||||
/* Nothing available, but need to return so that side effects get
|
/* Nothing available, but need to return so that side effects get
|
||||||
* handled, such as handling a message on a channel. */
|
* handled, such as handling a message on a channel. */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -5415,7 +5439,7 @@ WaitForChar(long msec)
|
|||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
#else
|
#else
|
||||||
return WaitForCharOrMouse(msec, NULL);
|
return WaitForCharOrMouse(msec, interrupted);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5423,10 +5447,12 @@ WaitForChar(long msec)
|
|||||||
* Wait "msec" msec until a character is available from the mouse or keyboard
|
* Wait "msec" msec until a character is available from the mouse or keyboard
|
||||||
* or from inbuf[].
|
* or from inbuf[].
|
||||||
* "msec" == -1 will block forever.
|
* "msec" == -1 will block forever.
|
||||||
|
* "interrupted" (if not NULL) is set to TRUE when no character is available
|
||||||
|
* but something else needs to be done.
|
||||||
* When a GUI is being used, this will never get called -- webb
|
* When a GUI is being used, this will never get called -- webb
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
WaitForCharOrMouse(long msec, int *break_loop)
|
WaitForCharOrMouse(long msec, int *interrupted)
|
||||||
{
|
{
|
||||||
#ifdef FEAT_MOUSE_GPM
|
#ifdef FEAT_MOUSE_GPM
|
||||||
int gpm_process_wanted;
|
int gpm_process_wanted;
|
||||||
@ -5473,9 +5499,9 @@ WaitForCharOrMouse(long msec, int *break_loop)
|
|||||||
# ifdef FEAT_MOUSE_GPM
|
# ifdef FEAT_MOUSE_GPM
|
||||||
gpm_process_wanted = 0;
|
gpm_process_wanted = 0;
|
||||||
avail = RealWaitForChar(read_cmd_fd, msec,
|
avail = RealWaitForChar(read_cmd_fd, msec,
|
||||||
&gpm_process_wanted, break_loop);
|
&gpm_process_wanted, interrupted);
|
||||||
# else
|
# else
|
||||||
avail = RealWaitForChar(read_cmd_fd, msec, NULL, break_loop);
|
avail = RealWaitForChar(read_cmd_fd, msec, NULL, interrupted);
|
||||||
# endif
|
# endif
|
||||||
if (!avail)
|
if (!avail)
|
||||||
{
|
{
|
||||||
@ -5498,7 +5524,7 @@ WaitForCharOrMouse(long msec, int *break_loop)
|
|||||||
;
|
;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
avail = RealWaitForChar(read_cmd_fd, msec, NULL, break_loop);
|
avail = RealWaitForChar(read_cmd_fd, msec, NULL, interrupted);
|
||||||
#endif
|
#endif
|
||||||
return avail;
|
return avail;
|
||||||
}
|
}
|
||||||
@ -5511,13 +5537,15 @@ WaitForCharOrMouse(long msec, int *break_loop)
|
|||||||
* 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
|
||||||
* 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.
|
* Or when a clientserver message is on the queue.
|
||||||
|
* "interrupted" (if not NULL) is set to TRUE when no character is available
|
||||||
|
* but something else needs to be done.
|
||||||
*/
|
*/
|
||||||
#if defined(__BEOS__)
|
#if defined(__BEOS__)
|
||||||
int
|
int
|
||||||
#else
|
#else
|
||||||
static int
|
static int
|
||||||
#endif
|
#endif
|
||||||
RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *break_loop)
|
RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *interrupted)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int result;
|
int result;
|
||||||
@ -5627,12 +5655,14 @@ RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *break_loop)
|
|||||||
#ifdef FEAT_JOB_CHANNEL
|
#ifdef FEAT_JOB_CHANNEL
|
||||||
nfd = channel_poll_setup(nfd, &fds);
|
nfd = channel_poll_setup(nfd, &fds);
|
||||||
#endif
|
#endif
|
||||||
|
if (interrupted != NULL)
|
||||||
|
*interrupted = FALSE;
|
||||||
|
|
||||||
ret = poll(fds, nfd, towait);
|
ret = poll(fds, nfd, towait);
|
||||||
|
|
||||||
result = ret > 0 && (fds[0].revents & POLLIN);
|
result = ret > 0 && (fds[0].revents & POLLIN);
|
||||||
if (break_loop != NULL && ret > 0)
|
if (result == 0 && interrupted != NULL && ret > 0)
|
||||||
*break_loop = TRUE;
|
*interrupted = TRUE;
|
||||||
|
|
||||||
# ifdef FEAT_MZSCHEME
|
# ifdef FEAT_MZSCHEME
|
||||||
if (ret == 0 && mzquantum_used)
|
if (ret == 0 && mzquantum_used)
|
||||||
@ -5679,7 +5709,6 @@ RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *break_loop)
|
|||||||
ret = channel_poll_check(ret, &fds);
|
ret = channel_poll_check(ret, &fds);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#else /* HAVE_SELECT */
|
#else /* HAVE_SELECT */
|
||||||
|
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
@ -5760,13 +5789,15 @@ select_eintr:
|
|||||||
# ifdef FEAT_JOB_CHANNEL
|
# ifdef FEAT_JOB_CHANNEL
|
||||||
maxfd = channel_select_setup(maxfd, &rfds, &wfds);
|
maxfd = channel_select_setup(maxfd, &rfds, &wfds);
|
||||||
# endif
|
# endif
|
||||||
|
if (interrupted != NULL)
|
||||||
|
*interrupted = FALSE;
|
||||||
|
|
||||||
ret = select(maxfd + 1, &rfds, &wfds, &efds, tvp);
|
ret = select(maxfd + 1, &rfds, &wfds, &efds, tvp);
|
||||||
result = ret > 0 && FD_ISSET(fd, &rfds);
|
result = ret > 0 && FD_ISSET(fd, &rfds);
|
||||||
if (result)
|
if (result)
|
||||||
--ret;
|
--ret;
|
||||||
if (break_loop != NULL && ret > 0)
|
else if (interrupted != NULL && ret > 0)
|
||||||
*break_loop = TRUE;
|
*interrupted = TRUE;
|
||||||
|
|
||||||
# ifdef EINTR
|
# ifdef EINTR
|
||||||
if (ret == -1 && errno == EINTR)
|
if (ret == -1 && errno == EINTR)
|
||||||
|
@ -47,7 +47,6 @@ int vpeekc_nomap(void);
|
|||||||
int vpeekc_any(void);
|
int vpeekc_any(void);
|
||||||
int char_avail(void);
|
int char_avail(void);
|
||||||
void vungetc(int c);
|
void vungetc(int c);
|
||||||
int inchar(char_u *buf, int maxlen, long wait_time, int tb_change_cnt);
|
|
||||||
int fix_input_buffer(char_u *buf, int len, int script);
|
int fix_input_buffer(char_u *buf, int len, int script);
|
||||||
int input_available(void);
|
int input_available(void);
|
||||||
int do_map(int maptype, char_u *arg, int mode, int abbrev);
|
int do_map(int maptype, char_u *arg, int mode, int abbrev);
|
||||||
|
@ -753,6 +753,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 */
|
||||||
|
/**/
|
||||||
|
1886,
|
||||||
/**/
|
/**/
|
||||||
1885,
|
1885,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user