diff options
| author | Eli Zaretskii | 2018-06-16 11:25:01 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2018-06-16 11:25:01 +0300 |
| commit | 2461266be1ea68a8c79af61abe850bb5a2c65040 (patch) | |
| tree | 31dc0a221acb8e3500127790d422af2fc68b645f | |
| parent | 31b2680bc955b99fd812d904a95271afbc3882db (diff) | |
| download | emacs-2461266be1ea68a8c79af61abe850bb5a2c65040.tar.gz emacs-2461266be1ea68a8c79af61abe850bb5a2c65040.zip | |
Prevent QUIT to top level inside 'while-no-input'
* lisp/subr.el (while-no-input): Handle the case when BODY
never tests quit-flag, and runs to completion even though
input arrives while BODY executes. (Bug#31692)
| -rw-r--r-- | lisp/subr.el | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/lisp/subr.el b/lisp/subr.el index 914112ccef5..4a2b797fa0c 100644 --- a/lisp/subr.el +++ b/lisp/subr.el | |||
| @@ -3520,9 +3520,31 @@ If BODY finishes, `while-no-input' returns whatever value BODY produced." | |||
| 3520 | (let ((catch-sym (make-symbol "input"))) | 3520 | (let ((catch-sym (make-symbol "input"))) |
| 3521 | `(with-local-quit | 3521 | `(with-local-quit |
| 3522 | (catch ',catch-sym | 3522 | (catch ',catch-sym |
| 3523 | (let ((throw-on-input ',catch-sym)) | 3523 | (let ((throw-on-input ',catch-sym) |
| 3524 | (or (input-pending-p) | 3524 | val) |
| 3525 | (progn ,@body))))))) | 3525 | (setq val (or (input-pending-p) |
| 3526 | (progn ,@body))) | ||
| 3527 | (cond | ||
| 3528 | ;; When input arrives while throw-on-input is non-nil, | ||
| 3529 | ;; kbd_buffer_store_buffered_event sets quit-flag to the | ||
| 3530 | ;; value of throw-on-input. If, when BODY finishes, | ||
| 3531 | ;; quit-flag still has the same value as throw-on-input, it | ||
| 3532 | ;; means BODY never tested quit-flag, and therefore ran to | ||
| 3533 | ;; completion even though input did arrive before it | ||
| 3534 | ;; finished. In that case, we must manually simulate what | ||
| 3535 | ;; 'throw' in process_quit_flag would do, and we must | ||
| 3536 | ;; reset quit-flag, because leaving it set will cause us | ||
| 3537 | ;; quit to top-level, which has undesirable consequences, | ||
| 3538 | ;; such as discarding input etc. We return t in that case | ||
| 3539 | ;; because input did arrive during execution of BODY. | ||
| 3540 | ((eq quit-flag throw-on-input) | ||
| 3541 | (setq quit-flag nil) | ||
| 3542 | t) | ||
| 3543 | ;; This is for when the user actually QUITs during | ||
| 3544 | ;; execution of BODY. | ||
| 3545 | (quit-flag | ||
| 3546 | nil) | ||
| 3547 | (t val))))))) | ||
| 3526 | 3548 | ||
| 3527 | (defmacro condition-case-unless-debug (var bodyform &rest handlers) | 3549 | (defmacro condition-case-unless-debug (var bodyform &rest handlers) |
| 3528 | "Like `condition-case' except that it does not prevent debugging. | 3550 | "Like `condition-case' except that it does not prevent debugging. |