Skip to content

Commit 833eb1d

Browse files
committed
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.
1 parent 2cab0e1 commit 833eb1d

File tree

6 files changed

+88
-48
lines changed

6 files changed

+88
-48
lines changed

src/channel.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3815,6 +3815,11 @@ channel_parse_messages(void)
38153815
int ret = FALSE;
38163816
int r;
38173817
ch_part_T part = PART_SOCK;
3818+
#ifdef ELAPSED_FUNC
3819+
ELAPSED_TYPE start_tv;
3820+
3821+
ELAPSED_INIT(start_tv);
3822+
#endif
38183823

38193824
++safe_to_invoke_callback;
38203825

@@ -3859,7 +3864,14 @@ channel_parse_messages(void)
38593864
r = may_invoke_callback(channel, part);
38603865
if (r == OK)
38613866
ret = TRUE;
3862-
if (channel_unref(channel) || r == OK)
3867+
if (channel_unref(channel) || (r == OK
3868+
#ifdef ELAPSED_FUNC
3869+
/* Limit the time we loop here to 100 msec, otherwise
3870+
* Vim becomes unresponsive when the callback takes
3871+
* more than a bit of time. */
3872+
&& ELAPSED_FUNC(start_tv) < 100L
3873+
#endif
3874+
))
38633875
{
38643876
/* channel was freed or something was done, start over */
38653877
channel = first_channel;

src/misc2.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6263,3 +6263,34 @@ parse_queued_messages(void)
62636263
# endif
62646264
}
62656265
#endif
6266+
6267+
#ifdef ELAPSED_TIMEVAL /* proto is defined in vim.h */
6268+
/*
6269+
* Return time in msec since "start_tv".
6270+
*/
6271+
long
6272+
elapsed(struct timeval *start_tv)
6273+
{
6274+
struct timeval now_tv;
6275+
6276+
gettimeofday(&now_tv, NULL);
6277+
return (now_tv.tv_sec - start_tv->tv_sec) * 1000L
6278+
+ (now_tv.tv_usec - start_tv->tv_usec) / 1000L;
6279+
}
6280+
#endif
6281+
6282+
#ifdef ELAPSED_TICKCOUNT
6283+
/*
6284+
* Return time in msec since "start_tick".
6285+
*/
6286+
long
6287+
elapsed(DWORD start_tick)
6288+
{
6289+
DWORD now = GetTickCount();
6290+
6291+
if (now < start_tick)
6292+
/* overflow */
6293+
return (long)now;
6294+
return (long)now - (long)start_tick;
6295+
}
6296+
#endif

src/os_unix.c

Lines changed: 26 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -376,21 +376,6 @@ mch_write(char_u *s, int len)
376376
RealWaitForChar(read_cmd_fd, p_wd, NULL, NULL);
377377
}
378378

379-
#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
380-
/*
381-
* Return time in msec since "start_tv".
382-
*/
383-
static long
384-
elapsed(struct timeval *start_tv)
385-
{
386-
struct timeval now_tv;
387-
388-
gettimeofday(&now_tv, NULL);
389-
return (now_tv.tv_sec - start_tv->tv_sec) * 1000L
390-
+ (now_tv.tv_usec - start_tv->tv_usec) / 1000L;
391-
}
392-
#endif
393-
394379
/*
395380
* mch_inchar(): low level input function.
396381
* Get a characters from the keyboard.
@@ -411,10 +396,10 @@ mch_inchar(
411396
int did_start_blocking = FALSE;
412397
long wait_time;
413398
long elapsed_time = 0;
414-
#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
415-
struct timeval start_tv;
399+
#ifdef ELAPSED_FUNC
400+
ELAPSED_TYPE start_tv;
416401

417-
gettimeofday(&start_tv, NULL);
402+
ELAPSED_INIT(start_tv);
418403
#endif
419404

420405
/* repeat until we got a character or waited long enough */
@@ -438,8 +423,8 @@ mch_inchar(
438423
else
439424
/* going to block after p_ut */
440425
wait_time = p_ut;
441-
#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
442-
elapsed_time = elapsed(&start_tv);
426+
#ifdef ELAPSED_FUNC
427+
elapsed_time = ELAPSED_FUNC(start_tv);
443428
#endif
444429
wait_time -= elapsed_time;
445430
if (wait_time < 0)
@@ -1554,18 +1539,16 @@ mch_input_isatty(void)
15541539

15551540
#ifdef FEAT_X11
15561541

1557-
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) \
1542+
# if defined(ELAPSED_TIMEVAL) \
15581543
&& (defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE))
15591544

1560-
static void xopen_message(struct timeval *start_tv);
1561-
15621545
/*
15631546
* Give a message about the elapsed time for opening the X window.
15641547
*/
15651548
static void
1566-
xopen_message(struct timeval *start_tv)
1549+
xopen_message(long elapsed_msec)
15671550
{
1568-
smsg((char_u *)_("Opening the X display took %ld msec"), elapsed(start_tv));
1551+
smsg((char_u *)_("Opening the X display took %ld msec"), elapsed_msec);
15691552
}
15701553
# endif
15711554
#endif
@@ -1864,11 +1847,11 @@ get_x11_windis(void)
18641847
#endif
18651848
if (x11_display != NULL)
18661849
{
1867-
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1850+
# ifdef ELAPSED_FUNC
18681851
if (p_verbose > 0)
18691852
{
18701853
verbose_enter();
1871-
xopen_message(&start_tv);
1854+
xopen_message(ELAPSED_FUNC(start_tv));
18721855
verbose_leave();
18731856
}
18741857
# endif
@@ -4630,8 +4613,8 @@ mch_call_shell(
46304613
ga_init2(&ga, 1, BUFLEN);
46314614

46324615
noread_cnt = 0;
4633-
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4634-
gettimeofday(&start_tv, NULL);
4616+
# ifdef ELAPSED_FUNC
4617+
ELAPSED_INIT(start_tv);
46354618
# endif
46364619
for (;;)
46374620
{
@@ -4666,8 +4649,8 @@ mch_call_shell(
46664649
/* Get extra characters when we don't have any.
46674650
* Reset the counter and timer. */
46684651
noread_cnt = 0;
4669-
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4670-
gettimeofday(&start_tv, NULL);
4652+
# ifdef ELAPSED_FUNC
4653+
ELAPSED_INIT(start_tv);
46714654
# endif
46724655
len = ui_inchar(ta_buf, BUFLEN, 10L, 0);
46734656
}
@@ -4886,10 +4869,10 @@ mch_call_shell(
48864869
if (got_int)
48874870
break;
48884871

4889-
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4872+
# ifdef ELAPSED_FUNC
48904873
if (wait_pid == 0)
48914874
{
4892-
long msec = elapsed(&start_tv);
4875+
long msec = ELAPSED_FUNC(start_tv);
48934876

48944877
/* Avoid that we keep looping here without
48954878
* checking for a CTRL-C for a long time. Don't
@@ -5632,15 +5615,14 @@ RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *interrupted)
56325615
/* May retry getting characters after an event was handled. */
56335616
# define MAY_LOOP
56345617

5635-
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
5618+
# ifdef ELAPSED_FUNC
56365619
/* Remember at what time we started, so that we know how much longer we
56375620
* should wait after being interrupted. */
5638-
# define USE_START_TV
56395621
long start_msec = msec;
5640-
struct timeval start_tv;
5622+
ELAPSED_TYPE start_tv;
56415623

56425624
if (msec > 0)
5643-
gettimeofday(&start_tv, NULL);
5625+
ELAPSED_INIT(start_tv);
56445626
# endif
56455627

56465628
/* Handle being called recursively. This may happen for the session
@@ -5947,9 +5929,9 @@ RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *interrupted)
59475929
/* We're going to loop around again, find out for how long */
59485930
if (msec > 0)
59495931
{
5950-
# ifdef USE_START_TV
5932+
# ifdef ELAPSED_FUNC
59515933
/* Compute remaining wait time. */
5952-
msec = start_msec - elapsed(&start_tv);
5934+
msec = start_msec - ELAPSED_FUNC(start_tv);
59535935
# else
59545936
/* Guess we got interrupted halfway. */
59555937
msec = msec / 2;
@@ -7046,11 +7028,11 @@ setup_term_clip(void)
70467028
#if defined(HAVE_SETJMP_H)
70477029
int (*oldIOhandler)();
70487030
#endif
7049-
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
7050-
struct timeval start_tv;
7031+
# ifdef ELAPSED_FUNC
7032+
ELAPSED_TYPE start_tv;
70517033

70527034
if (p_verbose > 0)
7053-
gettimeofday(&start_tv, NULL);
7035+
ELAPSED_INIT(start_tv);
70547036
# endif
70557037

70567038
/* Ignore X errors while opening the display */
@@ -7092,11 +7074,11 @@ setup_term_clip(void)
70927074
/* Catch terminating error of the X server connection. */
70937075
(void)XSetIOErrorHandler(x_IOerror_handler);
70947076

7095-
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
7077+
# ifdef ELAPSED_FUNC
70967078
if (p_verbose > 0)
70977079
{
70987080
verbose_enter();
7099-
xopen_message(&start_tv);
7081+
xopen_message(ELAPSED_FUNC(start_tv));
71007082
verbose_leave();
71017083
}
71027084
# endif

src/os_win32.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4287,9 +4287,6 @@ mch_system_piped(char *cmd, int options)
42874287
/* Get extra characters when we don't have any. Reset the
42884288
* counter and timer. */
42894289
noread_cnt = 0;
4290-
# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4291-
gettimeofday(&start_tv, NULL);
4292-
# endif
42934290
len = ui_inchar(ta_buf, BUFLEN, 10L, 0);
42944291
}
42954292
if (ta_len > 0 || len > 0)

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,8 @@ static char *(features[]) =
764764

765765
static int included_patches[] =
766766
{ /* Add new patch number below this line */
767+
/**/
768+
97,
767769
/**/
768770
96,
769771
/**/

src/vim.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2503,4 +2503,20 @@ typedef enum
25032503
# define OPEN_CHR_FILES
25042504
#endif
25052505

2506+
#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
2507+
# define ELAPSED_TIMEVAL
2508+
# define ELAPSED_INIT(v) gettimeofday(&v, NULL)
2509+
# define ELAPSED_FUNC(v) elapsed(&v)
2510+
# define ELAPSED_TYPE struct timeval
2511+
long elapsed(struct timeval *start_tv);
2512+
#else
2513+
# if defined(WIN32)
2514+
# define ELAPSED_TICKCOUNT
2515+
# define ELAPSED_INIT(v) v = GetTickCount
2516+
# define ELAPSED_FUNC(v) elapsed(v)
2517+
# define ELAPSED_TYPE DWORD
2518+
long elapsed(DWORD start_tick);
2519+
# endif
2520+
#endif
2521+
25062522
#endif /* VIM__H */

0 commit comments

Comments
 (0)