Somewhere between 2008-12-25 and 2009-01-17 the output for compilations in ABCL no longer shows up in the REPL but instead goes to the associated *inferior-lisp* buffer. Neither SBCL nor CLISP exhibit this behavior when invoked under the same Emacs/.emacs/SLIME combination, so I assume that something in the 'swank-abcl.lisp' hasn't kept pace with the rest of the system.
Could anyone give me a pointer to specific changes that I could look at to investigate fixing this? A basic ten-minute investigation of the diffs didn't reveal anything glaringly obvious to me.
Thanks, Mark evenson@panix.com
Mark Evenson wrote:
Somewhere between 2008-12-25 and 2009-01-17 the output for compilations in ABCL no longer shows up in the REPL but instead goes to the associated *inferior-lisp* buffer.
Actually the bug is much more general: *STANDARD-OUTPUT* remains bound to the *inferior-lisp* buffer instead of getting bound to a *SLIME-OUTPUT-BUFFER*.
Still looking for a clue as to what causes this…
After some investigation, I still don't understand what is going wrong here, but can report that after 2008-12-30, ABCL's SLIME definitely has the symptom that all output goes to the *inferior-lisp* buffer as opposed to the REPL bugger. And I should at least report what I have been able to determine more exactly about my confusion.
My main (mis)undestanding is that it seems as if the use of the WITH-CONNECTION macro is not properly binding *STANDARD-OUTPUT* to the output stream stored in the ENV field of the CONNECTION structure. Nor does the binding of the rest of the standard streams *ERROR-OUTPUT*, *DEBUG-IO*, *TERMINAL-IO* look correct. The code in CALL-WITH-CONNECTION, used by the WITH-CONNECTION macro reads:
(defun call-with-connection (connection function) (if (eq *emacs-connection* connection) (funcall function) (let ((*emacs-connection* connection) (*pending-slime-interrupts* '())) (without-slime-interrupts (with-swank-error-handler (*emacs-connection*) (with-io-redirection (*emacs-connection*) (call-with-debugger-hook #'swank-debugger-hook function)))))))
meaning that the WITH-IO-REDIRECTION macro will never be invoked if the REPL is being used as (eq *emacs-connection* connection)? This is the opposite of what I would expect from my understanding of what *emacs-connection* means.
But ECL seems to work with this code which is odd as ECL uses the same communication style (NIL) as ABCL, but ECL doesn't exhibit these sort of problems. I don't really undestand the intricacy of the closure that is made over the reader function created in the invocation of MAKE-REPL-INPUT-STREAM. The only difference in the code used by SLIME between ECL and ABCL is that ABCL doesn't use Gray streams (it doesn't really have them) as opposed to ECL, which does, in the MAKE-INPUT-STREAM/MAKE-OUTPUT-STREAM definitions. I can't think of what distinction might make, but I note it in case it strikes a chord with someone else.
The following function
(defun fix-standard-output (connection) (setf *standard-output* (cdr (find '*standard-output* (connection.env connection) :test #'equal :key #'car))))
when invoked on the REPL after SLIME starts via
CL-USER> (fix-standard-output swank::*emacs-connection*)
seems to restore the output behavior. Similar functions are probably needed for the other standard streams.
When I tried to bind *STANDARD-OUTPUT* to the value stored in CONNECTION.ENV at the same place *STANDARD-INPUT* is bound in SIMPLE-SERVE-REQUESTS, I get a stack overflow in the running of SWANK-LOADER.
* Mark Evenson [2009-01-23 13:34+0100] writes:
After some investigation, I still don't understand what is going wrong here, but can report that after 2008-12-30, ABCL's SLIME definitely has the symptom that all output goes to the *inferior-lisp* buffer as opposed to the REPL bugger. And I should at least report what I have been able to determine more exactly about my confusion.
I have an on old version of ABCL (0.0.9, don't know if that means much) but the IO redirection seems to work.
My main (mis)undestanding is that it seems as if the use of the WITH-CONNECTION macro is not properly binding *STANDARD-OUTPUT* to the output stream stored in the ENV field of the CONNECTION structure. Nor does the binding of the rest of the standard streams *ERROR-OUTPUT*, *DEBUG-IO*, *TERMINAL-IO* look correct. The code in CALL-WITH-CONNECTION, used by the WITH-CONNECTION macro reads:
(defun call-with-connection (connection function) (if (eq *emacs-connection* connection) (funcall function) (let ((*emacs-connection* connection) (*pending-slime-interrupts* '())) (without-slime-interrupts (with-swank-error-handler (*emacs-connection*) (with-io-redirection (*emacs-connection*) (call-with-debugger-hook #'swank-debugger-hook function)))))))
meaning that the WITH-IO-REDIRECTION macro will never be invoked if the REPL is being used as (eq *emacs-connection* connection)? This is the opposite of what I would expect from my understanding of what *emacs-connection* means.
Well, the name isn't great, but if *emacs-connection* is already bound then there should be no reason to bind *emacs-connection* and all the other dynamic bindings again.
If you add some debug code like (format *log-output* "stdout: ~a~%" *standard-output*) you should see the stream that Slime is using as *standard-output*.
But ECL seems to work with this code which is odd as ECL uses the same communication style (NIL) as ABCL, but ECL doesn't exhibit these sort of problems. I don't really undestand the intricacy of the closure that is made over the reader function created in the invocation of MAKE-REPL-INPUT-STREAM. The only difference in the code used by SLIME between ECL and ABCL is that ABCL doesn't use Gray streams (it doesn't really have them) as opposed to ECL, which does, in the MAKE-INPUT-STREAM/MAKE-OUTPUT-STREAM definitions. I can't think of what distinction might make, but I note it in case it strikes a chord with someone else.
MAKE-REPL-INPUT-STREAM makes a stream out of an input stream which polls the original stream and also Slime's socket for input. Slime requests are handled immediately and input for the original stream is just returned. In theory it should work to assign *standard-input* to such a stream and the native REPL would implicitly handle Slime requests.
The following function
(defun fix-standard-output (connection) (setf *standard-output* (cdr (find '*standard-output* (connection.env connection) :test #'equal :key #'car))))
when invoked on the REPL after SLIME starts via
CL-USER> (fix-standard-output swank::*emacs-connection*)
seems to restore the output behavior. Similar functions are probably needed for the other standard streams.
When I tried to bind *STANDARD-OUTPUT* to the value stored in CONNECTION.ENV at the same place *STANDARD-INPUT* is bound in SIMPLE-SERVE-REQUESTS, I get a stack overflow in the running of SWANK-LOADER.
At that point CONNECTION.ENV probably nil. It is initialized later, in CREATE-REPL.
Helmut.
Helmut Eller heller@common-lisp.net writes:
- Mark Evenson [2009-01-23 13:34+0100] writes:
After some investigation, I still don't understand what is going wrong here, but can report that after 2008-12-30, ABCL's SLIME definitely has the symptom that all output goes to the *inferior-lisp* buffer as opposed to the REPL bugger. And I should at least report what I have been able to determine more exactly about my confusion.
I have an on old version of ABCL (0.0.9, don't know if that means much) but the IO redirection seems to work.
The changes seem to break the test suite. After the `disconnect' test case, on reconnection the assertion
(assert (not *saved-global-streams*) ...)
in INIT-GLOBAL-STREAM-REDIRECTION fails.
-T.
ABCL is still having problems with SLIME HEAD. Here are some additional notes on what I have so far figured out.
1. The following kludgy fix can be placed in 'slime-init.lisp'. After the SLIME REPL has appeared, issue (SWANK::PATCH) to restore the streams to their "proper values".
(in-package :swank)
(defvar *borked-connections* (make-hash-table))
(defun patch () (if (gethash *emacs-connection* *borked-connections*) (warn "~A is already recorded as patched." *emacs-connection*) (setf (gethash *emacs-connection* *borked-connections*) *emacs-connection*)) (format *standard-output* "Fixing *STANDARD-OUTPUT*.~%") (let ((env (connection.env *emacs-connection*))) (loop :for (var . val) :in env :do (setf (symbol-value var) val))) (format *standard-output* "Fixed *STANDARD-OUTPUT*.~%"))
2. If one starts ABCL on the command line, loading swank via ASDF then issuing a (SWANK:CREATE-SERVER), one can connect via Emacs M-X slime-connection without any of the problems with the streams.
3. As far as I can track down the error, it seems that something in ABCL dies in the WITH-IO-REDIRECTION macro. If one patches 'swank.lisp' as in the attached patch, one observes that WITH-IO-REDIRECTION is entered twice, but only exited once. Why this doesn't toatlly bork the ABCL interaction still confused me. If one uncomments the HANDLER-CASE in the patch, one gets an inexplicable and unintelligible death of the ABCL process. Because connecting to ABCL running Swank not under Emacs (see point #2 above) works fine, getting the actual stack trace from the JVM doesn't look possible.
Tobias Rittweiler suggested on #lisp that it might be easier to fix ABCL's use of the threaded Swank interfaces rather than trying to get the NIL communication style to work. I'm working on that, but there is almost certainly a bug in ABCL showing up here (somehow losing the OUTPUT-FUNCTION in the closure over the WITH-CONNECTION macro is my current guess) that should be addressed as well somehow.
Mark evenson@panix.com