To: vim_dev@googlegroups.com Subject: Patch 7.4.1886 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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(). Files: src/getchar.c, src/proto/getchar.pro, src/os_unix.c *** ../vim-7.4.1885/src/getchar.c 2016-05-25 21:22:56.421828207 +0200 --- src/getchar.c 2016-06-03 22:48:33.339061035 +0200 *************** *** 129,134 **** --- 129,135 ---- static void map_free(mapblock_T **); static void validate_maphash(void); 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 static char_u *eval_map_expr(char_u *str, int c); #endif *************** *** 2941,2947 **** * Return the number of obtained characters. * Return -1 when end of input script reached. */ ! int inchar( char_u *buf, int maxlen, --- 2942,2948 ---- * Return the number of obtained characters. * Return -1 when end of input script reached. */ ! static int inchar( char_u *buf, int maxlen, *** ../vim-7.4.1885/src/proto/getchar.pro 2016-01-19 13:21:55.837334377 +0100 --- src/proto/getchar.pro 2016-06-03 22:46:02.479063110 +0200 *************** *** 47,53 **** int vpeekc_any(void); int char_avail(void); 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 input_available(void); int do_map(int maptype, char_u *arg, int mode, int abbrev); --- 47,52 ---- *** ../vim-7.4.1885/src/os_unix.c 2016-06-02 20:05:22.476384217 +0200 --- src/os_unix.c 2016-06-04 13:28:59.066334375 +0200 *************** *** 175,186 **** #endif static pid_t wait4pid(pid_t, waitstatus *); ! static int WaitForChar(long); ! static int WaitForCharOrMouse(long, int *break_loop); #if defined(__BEOS__) || defined(VMS) ! int RealWaitForChar(int, long, int *, int *break_loop); #else ! static int RealWaitForChar(int, long, int *, int *break_loop); #endif #ifdef FEAT_XCLIPBOARD --- 175,186 ---- #endif static pid_t wait4pid(pid_t, waitstatus *); ! static int WaitForChar(long msec, int *interrupted); ! static int WaitForCharOrMouse(long msec, int *interrupted); #if defined(__BEOS__) || defined(VMS) ! int RealWaitForChar(int, long, int *, int *interrupted); #else ! static int RealWaitForChar(int, long, int *, int *interrupted); #endif #ifdef FEAT_XCLIPBOARD *************** *** 385,390 **** --- 385,391 ---- int tb_change_cnt) { int len; + int interrupted = FALSE; #ifdef MESSAGE_QUEUE parse_queued_messages(); *************** *** 397,416 **** if (wtime >= 0) { ! while (!WaitForChar(wtime)) /* no character available */ { if (do_resize) handle_resize(); #ifdef FEAT_CLIENTSERVER ! else if (!server_waiting()) ! #else ! else #endif - /* return if not interrupted by resize or server */ - return 0; #ifdef MESSAGE_QUEUE ! parse_queued_messages(); #endif } } else /* wtime == -1 */ --- 398,428 ---- if (wtime >= 0) { ! /* TODO: when looping reduce wtime by the elapsed time. */ ! while (!WaitForChar(wtime, &interrupted)) { + /* no character available */ if (do_resize) + { handle_resize(); + continue; + } #ifdef FEAT_CLIENTSERVER ! if (server_waiting()) ! { ! parse_queued_messages(); ! continue; ! } #endif #ifdef MESSAGE_QUEUE ! if (interrupted) ! { ! parse_queued_messages(); ! continue; ! } #endif + /* return if not interrupted by resize or server */ + return 0; } } else /* wtime == -1 */ *************** *** 420,427 **** * flush all the swap files to disk. * Also done when interrupted by SIGWINCH. */ ! if (!WaitForChar(p_ut)) { #ifdef FEAT_AUTOCMD if (trigger_cursorhold() && maxlen >= 3 && !typebuf_changed(tb_change_cnt)) --- 432,440 ---- * flush all the swap files to disk. * Also done when interrupted by SIGWINCH. */ ! if (!WaitForChar(p_ut, &interrupted)) { + /* TODO: if interrupted is set loop to wait the remaining time. */ #ifdef FEAT_AUTOCMD if (trigger_cursorhold() && maxlen >= 3 && !typebuf_changed(tb_change_cnt)) *************** *** 436,442 **** } } ! for (;;) /* repeat until we got a character */ { long wtime_now = -1L; --- 449,456 ---- } } ! /* repeat until we got a character */ ! for (;;) { long wtime_now = -1L; *************** *** 462,471 **** * We want to be interrupted by the winch signal * or by an event on the monitored file descriptors. */ ! if (!WaitForChar(wtime_now)) { if (do_resize) /* interrupted by SIGWINCH signal */ ! handle_resize(); return 0; } --- 476,492 ---- * We want to be interrupted by the winch signal * or by an event on the monitored file descriptors. */ ! if (!WaitForChar(wtime_now, &interrupted)) { if (do_resize) /* interrupted by SIGWINCH signal */ ! continue; ! #ifdef MESSAGE_QUEUE ! if (interrupted || wtime_now > 0) ! { ! parse_queued_messages(); ! continue; ! } ! #endif return 0; } *************** *** 482,490 **** */ len = read_from_input_buf(buf, (long)maxlen); if (len > 0) - { return len; - } } } --- 503,509 ---- *************** *** 501,507 **** int mch_char_avail(void) { ! return WaitForChar(0L); } #if defined(HAVE_TOTAL_MEM) || defined(PROTO) --- 520,526 ---- int mch_char_avail(void) { ! return WaitForChar(0L, NULL); } #if defined(HAVE_TOTAL_MEM) || defined(PROTO) *************** *** 691,697 **** in_mch_delay = FALSE; } else ! WaitForChar(msec); } #if defined(HAVE_STACK_LIMIT) \ --- 710,716 ---- in_mch_delay = FALSE; } else ! WaitForChar(msec, NULL); } #if defined(HAVE_STACK_LIMIT) \ *************** *** 5229,5234 **** --- 5248,5257 ---- if (stderr_works) 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 */ } *************** *** 5376,5391 **** * from inbuf[]. * "msec" == -1 will block forever. * Invokes timer callbacks when needed. ! * When a GUI is being used, this will never get called -- webb * Returns TRUE when a character is available. */ static int ! WaitForChar(long msec) { #ifdef FEAT_TIMERS long due_time; long remaining = msec; - int break_loop = FALSE; int tb_change_cnt = typebuf.tb_change_cnt; /* When waiting very briefly don't trigger timers. */ --- 5399,5415 ---- * from inbuf[]. * "msec" == -1 will block forever. * Invokes timer callbacks when needed. ! * "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. + * When a GUI is being used, this will never get called -- webb */ static int ! WaitForChar(long msec, int *interrupted) { #ifdef FEAT_TIMERS long due_time; long remaining = msec; int tb_change_cnt = typebuf.tb_change_cnt; /* When waiting very briefly don't trigger timers. */ *************** *** 5404,5412 **** } if (due_time <= 0 || (msec > 0 && due_time > remaining)) due_time = remaining; ! if (WaitForCharOrMouse(due_time, &break_loop)) return TRUE; ! if (break_loop) /* Nothing available, but need to return so that side effects get * handled, such as handling a message on a channel. */ return FALSE; --- 5428,5436 ---- } if (due_time <= 0 || (msec > 0 && due_time > remaining)) due_time = remaining; ! if (WaitForCharOrMouse(due_time, interrupted)) return TRUE; ! if (interrupted != NULL && *interrupted) /* Nothing available, but need to return so that side effects get * handled, such as handling a message on a channel. */ return FALSE; *************** *** 5415,5421 **** } return FALSE; #else ! return WaitForCharOrMouse(msec, NULL); #endif } --- 5439,5445 ---- } return FALSE; #else ! return WaitForCharOrMouse(msec, interrupted); #endif } *************** *** 5423,5432 **** * Wait "msec" msec until a character is available from the mouse or keyboard * or from inbuf[]. * "msec" == -1 will block forever. * When a GUI is being used, this will never get called -- webb */ static int ! WaitForCharOrMouse(long msec, int *break_loop) { #ifdef FEAT_MOUSE_GPM int gpm_process_wanted; --- 5447,5458 ---- * Wait "msec" msec until a character is available from the mouse or keyboard * or from inbuf[]. * "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 */ static int ! WaitForCharOrMouse(long msec, int *interrupted) { #ifdef FEAT_MOUSE_GPM int gpm_process_wanted; *************** *** 5473,5481 **** # ifdef FEAT_MOUSE_GPM gpm_process_wanted = 0; avail = RealWaitForChar(read_cmd_fd, msec, ! &gpm_process_wanted, break_loop); # else ! avail = RealWaitForChar(read_cmd_fd, msec, NULL, break_loop); # endif if (!avail) { --- 5499,5507 ---- # ifdef FEAT_MOUSE_GPM gpm_process_wanted = 0; avail = RealWaitForChar(read_cmd_fd, msec, ! &gpm_process_wanted, interrupted); # else ! avail = RealWaitForChar(read_cmd_fd, msec, NULL, interrupted); # endif if (!avail) { *************** *** 5498,5504 **** ; #else ! avail = RealWaitForChar(read_cmd_fd, msec, NULL, break_loop); #endif return avail; } --- 5524,5530 ---- ; #else ! avail = RealWaitForChar(read_cmd_fd, msec, NULL, interrupted); #endif return avail; } *************** *** 5511,5523 **** * 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 clientserver message is on the queue. */ #if defined(__BEOS__) int #else static int #endif ! RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *break_loop) { int ret; int result; --- 5537,5551 ---- * 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 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__) int #else static int #endif ! RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *interrupted) { int ret; int result; *************** *** 5627,5638 **** #ifdef FEAT_JOB_CHANNEL nfd = channel_poll_setup(nfd, &fds); #endif ret = poll(fds, nfd, towait); result = ret > 0 && (fds[0].revents & POLLIN); ! if (break_loop != NULL && ret > 0) ! *break_loop = TRUE; # ifdef FEAT_MZSCHEME if (ret == 0 && mzquantum_used) --- 5655,5668 ---- #ifdef FEAT_JOB_CHANNEL nfd = channel_poll_setup(nfd, &fds); #endif + if (interrupted != NULL) + *interrupted = FALSE; ret = poll(fds, nfd, towait); result = ret > 0 && (fds[0].revents & POLLIN); ! if (result == 0 && interrupted != NULL && ret > 0) ! *interrupted = TRUE; # ifdef FEAT_MZSCHEME if (ret == 0 && mzquantum_used) *************** *** 5679,5685 **** ret = channel_poll_check(ret, &fds); #endif - #else /* HAVE_SELECT */ struct timeval tv; --- 5709,5714 ---- *************** *** 5760,5772 **** # ifdef FEAT_JOB_CHANNEL maxfd = channel_select_setup(maxfd, &rfds, &wfds); # endif ret = select(maxfd + 1, &rfds, &wfds, &efds, tvp); result = ret > 0 && FD_ISSET(fd, &rfds); if (result) --ret; ! if (break_loop != NULL && ret > 0) ! *break_loop = TRUE; # ifdef EINTR if (ret == -1 && errno == EINTR) --- 5789,5803 ---- # ifdef FEAT_JOB_CHANNEL maxfd = channel_select_setup(maxfd, &rfds, &wfds); # endif + if (interrupted != NULL) + *interrupted = FALSE; ret = select(maxfd + 1, &rfds, &wfds, &efds, tvp); result = ret > 0 && FD_ISSET(fd, &rfds); if (result) --ret; ! else if (interrupted != NULL && ret > 0) ! *interrupted = TRUE; # ifdef EINTR if (ret == -1 && errno == EINTR) *** ../vim-7.4.1885/src/version.c 2016-06-03 19:43:12.615214010 +0200 --- src/version.c 2016-06-04 13:30:51.134332834 +0200 *************** *** 755,756 **** --- 755,758 ---- { /* Add new patch number below this line */ + /**/ + 1886, /**/ -- Don't believe everything you hear or anything you say. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///