comparison src/os_unix.c @ 9205:c19eb05b19df v7.4.1886

commit https://github.com/vim/vim/commit/cda7764d8e65325d4524e5d6c3174121eeb12cad Author: Bram Moolenaar <Bram@vim.org> Date: Sat Jun 4 13:32:35 2016 +0200 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().
author Christian Brabandt <cb@256bit.org>
date Sat, 04 Jun 2016 13:45:05 +0200
parents 4b55d8e162d4
children 61e669c5da6f
comparison
equal deleted inserted replaced
9204:61b9dfe91682 9205:c19eb05b19df
173 #else 173 #else
174 typedef int waitstatus; 174 typedef int waitstatus;
175 #endif 175 #endif
176 static pid_t wait4pid(pid_t, waitstatus *); 176 static pid_t wait4pid(pid_t, waitstatus *);
177 177
178 static int WaitForChar(long); 178 static int WaitForChar(long msec, int *interrupted);
179 static int WaitForCharOrMouse(long, int *break_loop); 179 static int WaitForCharOrMouse(long msec, int *interrupted);
180 #if defined(__BEOS__) || defined(VMS) 180 #if defined(__BEOS__) || defined(VMS)
181 int RealWaitForChar(int, long, int *, int *break_loop); 181 int RealWaitForChar(int, long, int *, int *interrupted);
182 #else 182 #else
183 static int RealWaitForChar(int, long, int *, int *break_loop); 183 static int RealWaitForChar(int, long, int *, int *interrupted);
184 #endif 184 #endif
185 185
186 #ifdef FEAT_XCLIPBOARD 186 #ifdef FEAT_XCLIPBOARD
187 static int do_xterm_trace(void); 187 static int do_xterm_trace(void);
188 # define XT_TRACE_DELAY 50 /* delay for xterm tracing */ 188 # define XT_TRACE_DELAY 50 /* delay for xterm tracing */
383 int maxlen, 383 int maxlen,
384 long wtime, /* don't use "time", MIPS cannot handle it */ 384 long wtime, /* don't use "time", MIPS cannot handle it */
385 int tb_change_cnt) 385 int tb_change_cnt)
386 { 386 {
387 int len; 387 int len;
388 int interrupted = FALSE;
388 389
389 #ifdef MESSAGE_QUEUE 390 #ifdef MESSAGE_QUEUE
390 parse_queued_messages(); 391 parse_queued_messages();
391 #endif 392 #endif
392 393
395 while (do_resize) 396 while (do_resize)
396 handle_resize(); 397 handle_resize();
397 398
398 if (wtime >= 0) 399 if (wtime >= 0)
399 { 400 {
400 while (!WaitForChar(wtime)) /* no character available */ 401 /* TODO: when looping reduce wtime by the elapsed time. */
401 { 402 while (!WaitForChar(wtime, &interrupted))
403 {
404 /* no character available */
402 if (do_resize) 405 if (do_resize)
406 {
403 handle_resize(); 407 handle_resize();
408 continue;
409 }
404 #ifdef FEAT_CLIENTSERVER 410 #ifdef FEAT_CLIENTSERVER
405 else if (!server_waiting()) 411 if (server_waiting())
406 #else 412 {
407 else 413 parse_queued_messages();
408 #endif 414 continue;
409 /* return if not interrupted by resize or server */ 415 }
410 return 0; 416 #endif
411 #ifdef MESSAGE_QUEUE 417 #ifdef MESSAGE_QUEUE
412 parse_queued_messages(); 418 if (interrupted)
413 #endif 419 {
420 parse_queued_messages();
421 continue;
422 }
423 #endif
424 /* return if not interrupted by resize or server */
425 return 0;
414 } 426 }
415 } 427 }
416 else /* wtime == -1 */ 428 else /* wtime == -1 */
417 { 429 {
418 /* 430 /*
419 * If there is no character available within 'updatetime' seconds 431 * If there is no character available within 'updatetime' seconds
420 * flush all the swap files to disk. 432 * flush all the swap files to disk.
421 * Also done when interrupted by SIGWINCH. 433 * Also done when interrupted by SIGWINCH.
422 */ 434 */
423 if (!WaitForChar(p_ut)) 435 if (!WaitForChar(p_ut, &interrupted))
424 { 436 {
437 /* TODO: if interrupted is set loop to wait the remaining time. */
425 #ifdef FEAT_AUTOCMD 438 #ifdef FEAT_AUTOCMD
426 if (trigger_cursorhold() && maxlen >= 3 439 if (trigger_cursorhold() && maxlen >= 3
427 && !typebuf_changed(tb_change_cnt)) 440 && !typebuf_changed(tb_change_cnt))
428 { 441 {
429 buf[0] = K_SPECIAL; 442 buf[0] = K_SPECIAL;
434 #endif 447 #endif
435 before_blocking(); 448 before_blocking();
436 } 449 }
437 } 450 }
438 451
439 for (;;) /* repeat until we got a character */ 452 /* repeat until we got a character */
453 for (;;)
440 { 454 {
441 long wtime_now = -1L; 455 long wtime_now = -1L;
442 456
443 while (do_resize) /* window changed size */ 457 while (do_resize) /* window changed size */
444 handle_resize(); 458 handle_resize();
460 #endif 474 #endif
461 /* 475 /*
462 * We want to be interrupted by the winch signal 476 * We want to be interrupted by the winch signal
463 * or by an event on the monitored file descriptors. 477 * or by an event on the monitored file descriptors.
464 */ 478 */
465 if (!WaitForChar(wtime_now)) 479 if (!WaitForChar(wtime_now, &interrupted))
466 { 480 {
467 if (do_resize) /* interrupted by SIGWINCH signal */ 481 if (do_resize) /* interrupted by SIGWINCH signal */
468 handle_resize(); 482 continue;
483 #ifdef MESSAGE_QUEUE
484 if (interrupted || wtime_now > 0)
485 {
486 parse_queued_messages();
487 continue;
488 }
489 #endif
469 return 0; 490 return 0;
470 } 491 }
471 492
472 /* If input was put directly in typeahead buffer bail out here. */ 493 /* If input was put directly in typeahead buffer bail out here. */
473 if (typebuf_changed(tb_change_cnt)) 494 if (typebuf_changed(tb_change_cnt))
480 * For some other terminals this is quite slow, that's why we don't do 501 * For some other terminals this is quite slow, that's why we don't do
481 * it. 502 * it.
482 */ 503 */
483 len = read_from_input_buf(buf, (long)maxlen); 504 len = read_from_input_buf(buf, (long)maxlen);
484 if (len > 0) 505 if (len > 0)
485 {
486 return len; 506 return len;
487 }
488 } 507 }
489 } 508 }
490 509
491 static void 510 static void
492 handle_resize(void) 511 handle_resize(void)
499 * Return non-zero if a character is available. 518 * Return non-zero if a character is available.
500 */ 519 */
501 int 520 int
502 mch_char_avail(void) 521 mch_char_avail(void)
503 { 522 {
504 return WaitForChar(0L); 523 return WaitForChar(0L, NULL);
505 } 524 }
506 525
507 #if defined(HAVE_TOTAL_MEM) || defined(PROTO) 526 #if defined(HAVE_TOTAL_MEM) || defined(PROTO)
508 # ifdef HAVE_SYS_RESOURCE_H 527 # ifdef HAVE_SYS_RESOURCE_H
509 # include <sys/resource.h> 528 # include <sys/resource.h>
689 708
690 settmode(old_tmode); 709 settmode(old_tmode);
691 in_mch_delay = FALSE; 710 in_mch_delay = FALSE;
692 } 711 }
693 else 712 else
694 WaitForChar(msec); 713 WaitForChar(msec, NULL);
695 } 714 }
696 715
697 #if defined(HAVE_STACK_LIMIT) \ 716 #if defined(HAVE_STACK_LIMIT) \
698 || (!defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGSTACK)) 717 || (!defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGSTACK))
699 # define HAVE_CHECK_STACK_GROWTH 718 # define HAVE_CHECK_STACK_GROWTH
5227 /* See above for type of argv. */ 5246 /* See above for type of argv. */
5228 execvp(argv[0], argv); 5247 execvp(argv[0], argv);
5229 5248
5230 if (stderr_works) 5249 if (stderr_works)
5231 perror("executing job failed"); 5250 perror("executing job failed");
5251 #ifdef EXITFREE
5252 /* calling free_all_mem() here causes problems. Ignore valgrind
5253 * reporting possibly leaked memory. */
5254 #endif
5232 _exit(EXEC_FAILED); /* exec failed, return failure code */ 5255 _exit(EXEC_FAILED); /* exec failed, return failure code */
5233 } 5256 }
5234 5257
5235 /* parent */ 5258 /* parent */
5236 job->jv_pid = pid; 5259 job->jv_pid = pid;
5374 /* 5397 /*
5375 * Wait "msec" msec until a character is available from the mouse, keyboard, 5398 * Wait "msec" msec until a character is available from the mouse, keyboard,
5376 * from inbuf[]. 5399 * from inbuf[].
5377 * "msec" == -1 will block forever. 5400 * "msec" == -1 will block forever.
5378 * Invokes timer callbacks when needed. 5401 * Invokes timer callbacks when needed.
5402 * "interrupted" (if not NULL) is set to TRUE when no character is available
5403 * but something else needs to be done.
5404 * Returns TRUE when a character is available.
5379 * When a GUI is being used, this will never get called -- webb 5405 * When a GUI is being used, this will never get called -- webb
5380 * Returns TRUE when a character is available.
5381 */ 5406 */
5382 static int 5407 static int
5383 WaitForChar(long msec) 5408 WaitForChar(long msec, int *interrupted)
5384 { 5409 {
5385 #ifdef FEAT_TIMERS 5410 #ifdef FEAT_TIMERS
5386 long due_time; 5411 long due_time;
5387 long remaining = msec; 5412 long remaining = msec;
5388 int break_loop = FALSE;
5389 int tb_change_cnt = typebuf.tb_change_cnt; 5413 int tb_change_cnt = typebuf.tb_change_cnt;
5390 5414
5391 /* When waiting very briefly don't trigger timers. */ 5415 /* When waiting very briefly don't trigger timers. */
5392 if (msec >= 0 && msec < 10L) 5416 if (msec >= 0 && msec < 10L)
5393 return WaitForCharOrMouse(msec, NULL); 5417 return WaitForCharOrMouse(msec, NULL);
5402 /* timer may have used feedkeys() */ 5426 /* timer may have used feedkeys() */
5403 return FALSE; 5427 return FALSE;
5404 } 5428 }
5405 if (due_time <= 0 || (msec > 0 && due_time > remaining)) 5429 if (due_time <= 0 || (msec > 0 && due_time > remaining))
5406 due_time = remaining; 5430 due_time = remaining;
5407 if (WaitForCharOrMouse(due_time, &break_loop)) 5431 if (WaitForCharOrMouse(due_time, interrupted))
5408 return TRUE; 5432 return TRUE;
5409 if (break_loop) 5433 if (interrupted != NULL && *interrupted)
5410 /* Nothing available, but need to return so that side effects get 5434 /* Nothing available, but need to return so that side effects get
5411 * handled, such as handling a message on a channel. */ 5435 * handled, such as handling a message on a channel. */
5412 return FALSE; 5436 return FALSE;
5413 if (msec > 0) 5437 if (msec > 0)
5414 remaining -= due_time; 5438 remaining -= due_time;
5415 } 5439 }
5416 return FALSE; 5440 return FALSE;
5417 #else 5441 #else
5418 return WaitForCharOrMouse(msec, NULL); 5442 return WaitForCharOrMouse(msec, interrupted);
5419 #endif 5443 #endif
5420 } 5444 }
5421 5445
5422 /* 5446 /*
5423 * Wait "msec" msec until a character is available from the mouse or keyboard 5447 * Wait "msec" msec until a character is available from the mouse or keyboard
5424 * or from inbuf[]. 5448 * or from inbuf[].
5425 * "msec" == -1 will block forever. 5449 * "msec" == -1 will block forever.
5450 * "interrupted" (if not NULL) is set to TRUE when no character is available
5451 * but something else needs to be done.
5426 * When a GUI is being used, this will never get called -- webb 5452 * When a GUI is being used, this will never get called -- webb
5427 */ 5453 */
5428 static int 5454 static int
5429 WaitForCharOrMouse(long msec, int *break_loop) 5455 WaitForCharOrMouse(long msec, int *interrupted)
5430 { 5456 {
5431 #ifdef FEAT_MOUSE_GPM 5457 #ifdef FEAT_MOUSE_GPM
5432 int gpm_process_wanted; 5458 int gpm_process_wanted;
5433 #endif 5459 #endif
5434 #ifdef FEAT_XCLIPBOARD 5460 #ifdef FEAT_XCLIPBOARD
5471 } 5497 }
5472 # endif 5498 # endif
5473 # ifdef FEAT_MOUSE_GPM 5499 # ifdef FEAT_MOUSE_GPM
5474 gpm_process_wanted = 0; 5500 gpm_process_wanted = 0;
5475 avail = RealWaitForChar(read_cmd_fd, msec, 5501 avail = RealWaitForChar(read_cmd_fd, msec,
5476 &gpm_process_wanted, break_loop); 5502 &gpm_process_wanted, interrupted);
5477 # else 5503 # else
5478 avail = RealWaitForChar(read_cmd_fd, msec, NULL, break_loop); 5504 avail = RealWaitForChar(read_cmd_fd, msec, NULL, interrupted);
5479 # endif 5505 # endif
5480 if (!avail) 5506 if (!avail)
5481 { 5507 {
5482 if (input_available()) 5508 if (input_available())
5483 return 1; 5509 return 1;
5496 # endif 5522 # endif
5497 ) 5523 )
5498 ; 5524 ;
5499 5525
5500 #else 5526 #else
5501 avail = RealWaitForChar(read_cmd_fd, msec, NULL, break_loop); 5527 avail = RealWaitForChar(read_cmd_fd, msec, NULL, interrupted);
5502 #endif 5528 #endif
5503 return avail; 5529 return avail;
5504 } 5530 }
5505 5531
5506 #ifndef VMS 5532 #ifndef VMS
5509 * "msec" == 0 will check for characters once. 5535 * "msec" == 0 will check for characters once.
5510 * "msec" == -1 will block until a character is available. 5536 * "msec" == -1 will block until a character is available.
5511 * When a GUI is being used, this will not be used for input -- webb 5537 * When a GUI is being used, this will not be used for input -- webb
5512 * Or when a Linux GPM mouse event is waiting. 5538 * Or when a Linux GPM mouse event is waiting.
5513 * Or when a clientserver message is on the queue. 5539 * Or when a clientserver message is on the queue.
5540 * "interrupted" (if not NULL) is set to TRUE when no character is available
5541 * but something else needs to be done.
5514 */ 5542 */
5515 #if defined(__BEOS__) 5543 #if defined(__BEOS__)
5516 int 5544 int
5517 #else 5545 #else
5518 static int 5546 static int
5519 #endif 5547 #endif
5520 RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *break_loop) 5548 RealWaitForChar(int fd, long msec, int *check_for_gpm UNUSED, int *interrupted)
5521 { 5549 {
5522 int ret; 5550 int ret;
5523 int result; 5551 int result;
5524 #if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME) 5552 #if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME)
5525 static int busy = FALSE; 5553 static int busy = FALSE;
5625 } 5653 }
5626 # endif 5654 # endif
5627 #ifdef FEAT_JOB_CHANNEL 5655 #ifdef FEAT_JOB_CHANNEL
5628 nfd = channel_poll_setup(nfd, &fds); 5656 nfd = channel_poll_setup(nfd, &fds);
5629 #endif 5657 #endif
5658 if (interrupted != NULL)
5659 *interrupted = FALSE;
5630 5660
5631 ret = poll(fds, nfd, towait); 5661 ret = poll(fds, nfd, towait);
5632 5662
5633 result = ret > 0 && (fds[0].revents & POLLIN); 5663 result = ret > 0 && (fds[0].revents & POLLIN);
5634 if (break_loop != NULL && ret > 0) 5664 if (result == 0 && interrupted != NULL && ret > 0)
5635 *break_loop = TRUE; 5665 *interrupted = TRUE;
5636 5666
5637 # ifdef FEAT_MZSCHEME 5667 # ifdef FEAT_MZSCHEME
5638 if (ret == 0 && mzquantum_used) 5668 if (ret == 0 && mzquantum_used)
5639 /* MzThreads scheduling is required and timeout occurred */ 5669 /* MzThreads scheduling is required and timeout occurred */
5640 finished = FALSE; 5670 finished = FALSE;
5677 #ifdef FEAT_JOB_CHANNEL 5707 #ifdef FEAT_JOB_CHANNEL
5678 if (ret > 0) 5708 if (ret > 0)
5679 ret = channel_poll_check(ret, &fds); 5709 ret = channel_poll_check(ret, &fds);
5680 #endif 5710 #endif
5681 5711
5682
5683 #else /* HAVE_SELECT */ 5712 #else /* HAVE_SELECT */
5684 5713
5685 struct timeval tv; 5714 struct timeval tv;
5686 struct timeval *tvp; 5715 struct timeval *tvp;
5687 fd_set rfds, wfds, efds; 5716 fd_set rfds, wfds, efds;
5758 } 5787 }
5759 # endif 5788 # endif
5760 # ifdef FEAT_JOB_CHANNEL 5789 # ifdef FEAT_JOB_CHANNEL
5761 maxfd = channel_select_setup(maxfd, &rfds, &wfds); 5790 maxfd = channel_select_setup(maxfd, &rfds, &wfds);
5762 # endif 5791 # endif
5792 if (interrupted != NULL)
5793 *interrupted = FALSE;
5763 5794
5764 ret = select(maxfd + 1, &rfds, &wfds, &efds, tvp); 5795 ret = select(maxfd + 1, &rfds, &wfds, &efds, tvp);
5765 result = ret > 0 && FD_ISSET(fd, &rfds); 5796 result = ret > 0 && FD_ISSET(fd, &rfds);
5766 if (result) 5797 if (result)
5767 --ret; 5798 --ret;
5768 if (break_loop != NULL && ret > 0) 5799 else if (interrupted != NULL && ret > 0)
5769 *break_loop = TRUE; 5800 *interrupted = TRUE;
5770 5801
5771 # ifdef EINTR 5802 # ifdef EINTR
5772 if (ret == -1 && errno == EINTR) 5803 if (ret == -1 && errno == EINTR)
5773 { 5804 {
5774 /* Check whether window has been resized, EINTR may be caused by 5805 /* Check whether window has been resized, EINTR may be caused by