[slime-devel] Problems with slime using sbcl on winXP (emacsW32)

Helmut Eller heller at common-lisp.net
Sat Dec 6 08:27:30 UTC 2008

* Thomas Karolski [2008-12-05 22:04+0100] writes:

> Helmut Eller schrieb:
>> Does READ-CHAR-NO-HANG work properly on socket streams?
>> There is a comment in HANDLE-LISTEN (in win32.lisp)
> Not sure - how could I test that?

For example with:

 (let ((socket (make-instance 'sb-bsd-sockets:inet-socket
			      :type :stream :protocol :tcp)))
   (setf (sb-bsd-sockets:sockopt-reuse-address socket) t)
   (sb-bsd-sockets:socket-bind socket #(0 0 0 0) 5000)
   (sb-bsd-sockets:socket-listen socket 5)
	 (sb-bsd-sockets:socket-accept socket)
	 :output t :input t :element-type 'character)
     (sb-bsd-sockets:socket-close socket))))

This creates a socket, waits for someone to connect, and calls
read-char-no-hang on the new stream.
Start this in SBCL and execute  "telnet localhost 5000"
in a shell.  read-char-no-hang should return nil as soon
as the telnet client connects.  

If it just waits, then you can type something into the telnet window and
the first char should appear on the SBCL side.  In this case
read-char-no-hang doesn't work properly, it works like the ordinary

> I think it should work on gray
> streams, but I'm not sure what slime is using.

In this situation it's a fd-stream and the fd is a socket.

>> I suspect that WAIT-FOR-EVENT/EVENT-LOOP (in swank.lisp) blocks even
>> though the timeout argument is t.  To see if that's actually the case,
>> you could generate some debug output in WAIT-FOR-EVENT/EVENT-LOOP.  It's
>> the easiest if you use LOG-EVENT for that.
> Changed wait-for-event/event-loop into:
> --------------------------------
> (defun wait-for-event/event-loop (pattern timeout)
>  (assert (or (not timeout) (eq timeout t)))
>  (log-event "wait-for-event/event-loop: ~s ~s~%" pattern timeout)
>  (let ((r (loop          (check-slime-interrupts)
>            (let ((event (poll-for-event pattern)))
>              (when event (return (car event))))
>            (log-event "pre wait-for-input~%")
>            (let ((events-enqueued *events-enqueued*)
>                  (ready (wait-for-input (list (current-socket-io))
> timeout)))
>              (log-event "after wait-for-input~%")
>              (cond ((and timeout (not ready))
>                     (return (values nil t)))
>                    ((or (/= events-enqueued *events-enqueued*)
>                         (eq ready :interrupt))
>                     ;; rescan event queue, interrupts may enqueue new
> events
>                     )
>                    (t
>                     (assert (equal ready (list (current-socket-io))))
>                     (dispatch-event (decode-message
> (current-socket-io)))))))))
>    (log-event "-wait-for-event/event-loop: ~s~%" r)
>    r))
> --------------------------------
> I attached the new *inferior-lisp* buffer.
> The last message is "pre wait-for-input", which indicates that its
> hanging inside wait-for-input. I also tried putting a log-event before
> read-char-no-hang inside wait-for-input, but that didn't seem to get
> logged for some reason.

wait-for-input is in swank-backend.lisp and in swank-sbcl.lisp.  Perhaps
you added it in the wrong file.  Those are also in different packages
so,  you probably need something like 
(funcall (read-from-string "swank::log-event") ...)

> Seeing this I guess you're right. Is there any way to work around this
> issue? - it does work for earlier calls to wait-for-input after all
> (though those all don't have a timeout).

The best solution would be to fix HANDLE-LISTEN, but I don't know how to
do that.

As a workaround you can probably replace
    (wait-for-event `(:sldb-return ,(1+ level)) t) ; clean event-queue
in sldb-loop with:
    (poll-for-event `(:sldb-return ,(1+ level)))


More information about the slime-devel mailing list