To: vim_dev@googlegroups.com Subject: Patch 8.0.0097 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.0.0097 Problem: When a channel callback consumes a lot of time Vim becomes unresponsive. (skywind) Solution: Bail out of checking channel readahead after 100 msec. Files: src/os_unix.c, src/misc2.c, src/vim.h, src/os_win32.c *** ../vim-8.0.0096/src/os_unix.c 2016-11-17 17:25:28.212093109 +0100 --- src/os_unix.c 2016-11-24 17:10:57.847711807 +0100 *************** *** 376,396 **** RealWaitForChar(read_cmd_fd, p_wd, NULL, NULL); } - #if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) - /* - * Return time in msec since "start_tv". - */ - static long - elapsed(struct timeval *start_tv) - { - struct timeval now_tv; - - gettimeofday(&now_tv, NULL); - return (now_tv.tv_sec - start_tv->tv_sec) * 1000L - + (now_tv.tv_usec - start_tv->tv_usec) / 1000L; - } - #endif - /* * mch_inchar(): low level input function. * Get a characters from the keyboard. --- 376,381 ---- *************** *** 411,420 **** int did_start_blocking = FALSE; long wait_time; long elapsed_time = 0; ! #if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) ! struct timeval start_tv; ! gettimeofday(&start_tv, NULL); #endif /* repeat until we got a character or waited long enough */ --- 396,405 ---- int did_start_blocking = FALSE; long wait_time; long elapsed_time = 0; ! #ifdef ELAPSED_FUNC ! ELAPSED_TYPE start_tv; ! ELAPSED_INIT(start_tv); #endif /* repeat until we got a character or waited long enough */ *************** *** 438,445 **** else /* going to block after p_ut */ wait_time = p_ut; ! #if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) ! elapsed_time = elapsed(&start_tv); #endif wait_time -= elapsed_time; if (wait_time < 0) --- 423,430 ---- else /* going to block after p_ut */ wait_time = p_ut; ! #ifdef ELAPSED_FUNC ! elapsed_time = ELAPSED_FUNC(start_tv); #endif wait_time -= elapsed_time; if (wait_time < 0) *************** *** 1554,1571 **** #ifdef FEAT_X11 ! # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) \ && (defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE)) - static void xopen_message(struct timeval *start_tv); - /* * Give a message about the elapsed time for opening the X window. */ static void ! xopen_message(struct timeval *start_tv) { ! smsg((char_u *)_("Opening the X display took %ld msec"), elapsed(start_tv)); } # endif #endif --- 1539,1554 ---- #ifdef FEAT_X11 ! # if defined(ELAPSED_TIMEVAL) \ && (defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE)) /* * Give a message about the elapsed time for opening the X window. */ static void ! xopen_message(long elapsed_msec) { ! smsg((char_u *)_("Opening the X display took %ld msec"), elapsed_msec); } # endif #endif *************** *** 1864,1874 **** #endif if (x11_display != NULL) { ! # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) if (p_verbose > 0) { verbose_enter(); ! xopen_message(&start_tv); verbose_leave(); } # endif --- 1847,1857 ---- #endif if (x11_display != NULL) { ! # ifdef ELAPSED_FUNC if (p_verbose > 0) { verbose_enter(); ! xopen_message(ELAPSED_FUNC(start_tv)); verbose_leave(); } # endif *************** *** 4630,4637 **** ga_init2(&ga, 1, BUFLEN); noread_cnt = 0; ! # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) ! gettimeofday(&start_tv, NULL); # endif for (;;) { --- 4613,4620 ---- ga_init2(&ga, 1, BUFLEN); noread_cnt = 0; ! # ifdef ELAPSED_FUNC ! ELAPSED_INIT(start_tv); # endif for (;;) { *************** *** 4666,4673 **** /* Get extra characters when we don't have any. * Reset the counter and timer. */ noread_cnt = 0; ! # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) ! gettimeofday(&start_tv, NULL); # endif len = ui_inchar(ta_buf, BUFLEN, 10L, 0); } --- 4649,4656 ---- /* Get extra characters when we don't have any. * Reset the counter and timer. */ noread_cnt = 0; ! # ifdef ELAPSED_FUNC ! ELAPSED_INIT(start_tv); # endif len = ui_inchar(ta_buf, BUFLEN, 10L, 0); } *************** *** 4886,4895 **** if (got_int) break; ! # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) if (wait_pid == 0) { ! long msec = elapsed(&start_tv); /* Avoid that we keep looping here without * checking for a CTRL-C for a long time. Don't --- 4869,4878 ---- if (got_int) break; ! # ifdef ELAPSED_FUNC if (wait_pid == 0) { ! long msec = ELAPSED_FUNC(start_tv); /* Avoid that we keep looping here without * checking for a CTRL-C for a long time. Don't *************** *** 5632,5646 **** /* May retry getting characters after an event was handled. */ # define MAY_LOOP ! # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) /* Remember at what time we started, so that we know how much longer we * should wait after being interrupted. */ - # define USE_START_TV long start_msec = msec; ! struct timeval start_tv; if (msec > 0) ! gettimeofday(&start_tv, NULL); # endif /* Handle being called recursively. This may happen for the session --- 5615,5628 ---- /* May retry getting characters after an event was handled. */ # define MAY_LOOP ! # ifdef ELAPSED_FUNC /* Remember at what time we started, so that we know how much longer we * should wait after being interrupted. */ long start_msec = msec; ! ELAPSED_TYPE start_tv; if (msec > 0) ! ELAPSED_INIT(start_tv); # endif /* Handle being called recursively. This may happen for the session *************** *** 5947,5955 **** /* We're going to loop around again, find out for how long */ if (msec > 0) { ! # ifdef USE_START_TV /* Compute remaining wait time. */ ! msec = start_msec - elapsed(&start_tv); # else /* Guess we got interrupted halfway. */ msec = msec / 2; --- 5929,5937 ---- /* We're going to loop around again, find out for how long */ if (msec > 0) { ! # ifdef ELAPSED_FUNC /* Compute remaining wait time. */ ! msec = start_msec - ELAPSED_FUNC(start_tv); # else /* Guess we got interrupted halfway. */ msec = msec / 2; *************** *** 7046,7056 **** #if defined(HAVE_SETJMP_H) int (*oldIOhandler)(); #endif ! # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) ! struct timeval start_tv; if (p_verbose > 0) ! gettimeofday(&start_tv, NULL); # endif /* Ignore X errors while opening the display */ --- 7028,7038 ---- #if defined(HAVE_SETJMP_H) int (*oldIOhandler)(); #endif ! # ifdef ELAPSED_FUNC ! ELAPSED_TYPE start_tv; if (p_verbose > 0) ! ELAPSED_INIT(start_tv); # endif /* Ignore X errors while opening the display */ *************** *** 7092,7102 **** /* Catch terminating error of the X server connection. */ (void)XSetIOErrorHandler(x_IOerror_handler); ! # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) if (p_verbose > 0) { verbose_enter(); ! xopen_message(&start_tv); verbose_leave(); } # endif --- 7074,7084 ---- /* Catch terminating error of the X server connection. */ (void)XSetIOErrorHandler(x_IOerror_handler); ! # ifdef ELAPSED_FUNC if (p_verbose > 0) { verbose_enter(); ! xopen_message(ELAPSED_FUNC(start_tv)); verbose_leave(); } # endif *** ../vim-8.0.0096/src/misc2.c 2016-11-10 20:01:41.193582919 +0100 --- src/misc2.c 2016-11-24 16:57:53.768987660 +0100 *************** *** 6263,6265 **** --- 6263,6296 ---- # endif } #endif + + #ifdef ELAPSED_TIMEVAL /* proto is defined in vim.h */ + /* + * Return time in msec since "start_tv". + */ + long + elapsed(struct timeval *start_tv) + { + struct timeval now_tv; + + gettimeofday(&now_tv, NULL); + return (now_tv.tv_sec - start_tv->tv_sec) * 1000L + + (now_tv.tv_usec - start_tv->tv_usec) / 1000L; + } + #endif + + #ifdef ELAPSED_TICKCOUNT + /* + * Return time in msec since "start_tick". + */ + long + elapsed(DWORD start_tick) + { + DWORD now = GetTickCount(); + + if (now < start_tick) + /* overflow */ + return (long)now; + return (long)now - (long)start_tick; + } + #endif *** ../vim-8.0.0096/src/vim.h 2016-11-10 20:01:41.201582868 +0100 --- src/vim.h 2016-11-24 16:58:55.288576323 +0100 *************** *** 2503,2506 **** --- 2503,2522 ---- # define OPEN_CHR_FILES #endif + #if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) + # define ELAPSED_TIMEVAL + # define ELAPSED_INIT(v) gettimeofday(&v, NULL) + # define ELAPSED_FUNC(v) elapsed(&v) + # define ELAPSED_TYPE struct timeval + long elapsed(struct timeval *start_tv); + #else + # if defined(WIN32) + # define ELAPSED_TICKCOUNT + # define ELAPSED_INIT(v) v = GetTickCount + # define ELAPSED_FUNC(v) elapsed(v) + # define ELAPSED_TYPE DWORD + long elapsed(DWORD start_tick); + # endif + #endif + #endif /* VIM__H */ *** ../vim-8.0.0096/src/os_win32.c 2016-11-19 17:28:41.577810144 +0100 --- src/os_win32.c 2016-11-24 16:46:08.177711935 +0100 *************** *** 4287,4295 **** /* Get extra characters when we don't have any. Reset the * counter and timer. */ noread_cnt = 0; - # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) - gettimeofday(&start_tv, NULL); - # endif len = ui_inchar(ta_buf, BUFLEN, 10L, 0); } if (ta_len > 0 || len > 0) --- 4287,4292 ---- *** ../vim-8.0.0096/src/channel.c 2016-11-17 17:25:28.208093136 +0100 --- src/channel.c 2016-11-24 17:04:11.666462247 +0100 *************** *** 3815,3820 **** --- 3815,3825 ---- int ret = FALSE; int r; ch_part_T part = PART_SOCK; + #ifdef ELAPSED_FUNC + ELAPSED_TYPE start_tv; + + ELAPSED_INIT(start_tv); + #endif ++safe_to_invoke_callback; *************** *** 3859,3865 **** r = may_invoke_callback(channel, part); if (r == OK) ret = TRUE; ! if (channel_unref(channel) || r == OK) { /* channel was freed or something was done, start over */ channel = first_channel; --- 3864,3877 ---- r = may_invoke_callback(channel, part); if (r == OK) ret = TRUE; ! if (channel_unref(channel) || (r == OK ! #ifdef ELAPSED_FUNC ! /* Limit the time we loop here to 100 msec, otherwise ! * Vim becomes unresponsive when the callback takes ! * more than a bit of time. */ ! && ELAPSED_FUNC(start_tv) < 100L ! #endif ! )) { /* channel was freed or something was done, start over */ channel = first_channel; *** ../vim-8.0.0096/src/version.c 2016-11-24 15:09:03.413856612 +0100 --- src/version.c 2016-11-24 17:16:25.453392518 +0100 *************** *** 766,767 **** --- 766,769 ---- { /* Add new patch number below this line */ + /**/ + 97, /**/ -- hundred-and-one symptoms of being an internet addict: 39. You move into a new house and decide to Netscape before you landscape. /// 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 ///