If I run the example in the CLHS page of CLEAR-INPUT,
Example: HU> (defun read-sleepily (&optional (clear-p nil) (zzz 0)) (list (progn (print '>) (read)) ;; Note that input typed within the first ZZZ seconds ;; will be discarded. (progn (print '>) (if zzz (sleep zzz)) (print '>>) (if clear-p (clear-input)) (read)))) READ-SLEEPILY HU> (read-sleepily t 10)
10
20
30
End Example
I get this:
Recursive lock attempt #S(SB-THREAD:MUTEX :NAME "buffer read lock" :%OWNER #<SB-THREAD:THREAD "repl-thread" RUNNING {BC10BB1}> :STATE 1). [Condition of type SIMPLE-ERROR]
Backtrace: 0: (SB-THREAD:GET-MUTEX #<unavailable argument> #<unavailable argument> #<unavailable argument>) 1: ((FLET #:WITHOUT-INTERRUPTS-BODY-[CALL-WITH-MUTEX]477)) 2: ((LAMBDA (SWANK-BACKEND::LOCK FUNCTION)) #S(SB-THREAD:MUTEX :NAME "buffer read lock" :%OWNER #<SB-THREAD:THREAD "repl-thread" RUNNING {BC10BB1}> :STATE 1) #<CLOSURE (LAMBDA NIL) {C1FDE25}>) 3: (SWANK-BACKEND:CALL-WITH-LOCK-HELD #S(SB-THREAD:MUTEX :NAME "buffer read lock" :%OWNER #<SB-THREAD:THREAD "repl-thread" RUNNING {BC10BB1}> :STATE 1) #<CLOSURE (LAMBDA NIL) {C1FDE25}>) 4: ((SB-PCL::FAST-METHOD SB-GRAY:STREAM-CLEAR-INPUT (SWANK-BACKEND::SLIME-INPUT-STREAM)) #(3 NIL 4 NIL 5 NIL) #<unused argument> #<SWANK-BACKEND::SLIME-INPUT-STREAM {B9C4011}>) 5: (CLEAR-INPUT #<SWANK-BACKEND::SLIME-INPUT-STREAM {B9C4011}>) 6: (SWANK::CLEAR-USER-INPUT) 7: (SWANK::REPL-EVAL "30 ")
Thank you for the bug report. Unfortunately, this problem isn't easy to fix. The problem is that READ-CHAR and other blocking input functions on the slime-input-stream enter a nested/recursive event processing loop. The loop is terminated on a matching input event but the other events are processed inside READ-CHAR.
This nested event loop is obviously problematic. In this situation it would probably be more appropriate to queue the non-matching events and process them later. OTOH, it feels natural to run the debugger in an nested event loop. It's not so obvious when queueing is appropriate, especially if the same code should be useable with and without threads.
Another problem is that the REPL buffer only switches to "read-mode" if the Lisp side called something like READ-CHAR. Since Emacs can't reliably know whether the Lisp side is still/already inside READ-CHAR[-NO-HANG] it would be better to always send the same events and let the Lisp side make the final decision.
The problem is known but it doesn't seem to occur all that often in day-to-day use. Fixing it requires some redesign and it's not entirely clear how to do this "right".
Helmut.