Subject: Re: bug#27036: Acknowledgement (25.1; Blocking call to accept-process-output with quit inhibited!!)

From: Dmitry Gutov <[email-masked]>
Date: Sat, 27 May 2017 03:22:19 +0300

On 5/26/17 4:17 PM, Francesco Potortì wrote:

> if Octave is running a long command it
> locks Emacs until the long command execution finishes and the prompt is
> returned.

Yes, this problem should be common for all modes that use the REPL for 
fetching information like this. E.g. python-eldoc-function.

Normally, we don't see long-running commands in the user REPL. Or don't 
expect the user to switch back to the source buffer and continue 
editing. Octave might be a significant exception in that regard.

Anyway, please try the attached combined patch and see if it fixes your 
problem.

> It also makes damage in some other cases that I cannot identify.

If you have company-mode installed and enabled, similar problem can 
occur (when completion is triggered automatically).
diff --git a/lisp/progmodes/octave.el b/lisp/progmodes/octave.el
index ac9ba63..d0a92d8 100644
--- a/lisp/progmodes/octave.el
+++ b/lisp/progmodes/octave.el
@@ -938,12 +938,19 @@ inferior-octave-send-list-and-digest
 	(while (setq string (car list))
 	  (setq inferior-octave-output-string nil
 		inferior-octave-receive-in-progress t)
-	  (comint-send-string proc string)
-	  (while inferior-octave-receive-in-progress
-	    (accept-process-output proc))
+	  (process-send-string proc string)
+	  (while
+              (and inferior-octave-receive-in-progress
+                   (with-local-quit
+                     (accept-process-output proc))))
 	  (setq list (cdr list)))
       (set-process-filter proc filter))))
 
+(defun inferior-octave--busy-p ()
+  (not
+   (buffer-local-value 'comint-last-prompt
+                       (process-buffer inferior-octave-process))))
+
 (defvar inferior-octave-directory-tracker-resync nil)
 (make-variable-buffer-local 'inferior-octave-directory-tracker-resync)
 
@@ -1586,19 +1593,21 @@ octave-eldoc-message-style
 (defvar octave-eldoc-cache nil)
 
 (defun octave-eldoc-function-signatures (fn)
-  (unless (equal fn (car octave-eldoc-cache))
-    (inferior-octave-send-list-and-digest
-     (list (format "print_usage ('%s');\n" fn)))
-    (let (result)
-      (dolist (line inferior-octave-output-list)
-        (when (string-match
-               "\\s-*\\(?:--[^:]+\\|usage\\):\\s-*\\(.*\\)$"
-               line)
-          (push (match-string 1 line) result)))
-      (setq octave-eldoc-cache
-            (cons (substring-no-properties fn)
-                  (nreverse result)))))
-  (cdr octave-eldoc-cache))
+  (if (equal fn (car octave-eldoc-cache))
+      (cdr octave-eldoc-cache)
+    (unless (inferior-octave--busy-p)
+      (inferior-octave-send-list-and-digest
+       (list (format "print_usage ('%s');\n" fn)))
+      (let (result)
+        (dolist (line inferior-octave-output-list)
+          (when (string-match
+                 "\\s-*\\(?:--[^:]+\\|usage\\):\\s-*\\(.*\\)$"
+                 line)
+            (push (match-string 1 line) result)))
+        (setq octave-eldoc-cache
+              (cons (substring-no-properties fn)
+                    (nreverse result))))
+      (cdr octave-eldoc-cache))))
 
 (defun octave-eldoc-function ()
   "A function for `eldoc-documentation-function' (which see)."