Considering the following code:

    (in-package #:cl-user)

    (defconstant +block-size+ 5)

    (let ((buffer (make-string +block-size+)))
      (defun read->echo (in out)
        ;; Can I make use (MAKE-ECHO-STREAM IN OUT) with READ-N-BYTES ?
        ;; Is there any benefit to using READ-N-BYTES instead of
        ;; READ-SEQUENCE ?
        (let ((bytes-read (sys:read-n-bytes in buffer 0 +block-size+ nil)))
          (format t "buffer => ~S~%bytes-read => ~A~%" buffer bytes-read)
          (write-string buffer out :start 0 :end bytes-read)
          bytes-read)))

    (defvar *shelf3*)
    (defvar *expect-buffer*
      (make-array '(0) :element-type 'base-char :fill-pointer 0
                  :adjustable t))

    (defun shelf3--make ()
      (when (and (boundp '*shelf3*) *shelf3*)
        (error "*shelf3* is already bound: ~A" *shelf3*))
      (setf *shelf3*
            (ext:run-program "telnet" '("127.0.0.1")
                             :wait nil :pty t :input t :output t :error t)))

    (defun shelf3--add-fd-handler ()
      (sys:add-fd-handler (sys:fd-stream-fd (ext:process-pty *shelf3*))
                          :input
                          ;; Why is the handler being called before one
                          ;; even calls SYS:SERVE-EVENT ?  I want to be
                          ;; able to set this handler and then call
                          ;; SYS:SERVE-EVENT to have the handler invoked.
                          (with-output-to-string (s *expect-buffer*)
                            (lambda (fd)
                              (declare (ignorable fd))
                              (read->echo (ext:process-pty *shelf3*) s)
                              (format t "*expect-buffer* => ~S~%"
                                      *expect-buffer*)))))
    
    (defun shelf3--read-5 ()
      (dotimes (n 5)
        (format t "~A" (read-char (process-pty *shelf3*))))
      (format t "~%"))

I would expect to be able to use it as follows (hypothetical):

    (shelf3--make) => #<process pid :RUNNING>
    (shelf3--add-fd-handler) => #<Handler for INPUT on ...>
    (sys:serve-event 1) => t
        buffer => "Tryin"
        bytes-read => 5
        *expect-buffer* => "Tryin"
    (sys:serve-event 1) => t
        buffer => "g 127"
        bytes-read => 5
        *expect-buffer* => "Trying 127"
    (sys:serve-event 1) => t
        buffer => ".0.0."
        bytes-read => 5
        *expect-buffer* => "Trying 127.0.0."
    (sys:serve-event 1) => t
        buffer => "1..."
        bytes-read => 5
        *expect-buffer* => "Trying 127.0.0.1..."

But I'm not getting that.  Is that not the way that ADD-FD-HANDLER and
SERVE-EVENT are meant to be used?  I'm getting something like this...

    % cmucl -eval '(progn (load "new-expect"))'
    #| ... |#
    CMU Common Lisp 18e, running on gsdapp04
    With core: #| ... |#
    Dumped on: Tue, 2003-04-08 13:23:10-05:00 on achat
    See <http://www.cons.org/cmucl/> for support information.
    Loaded subsystems:
        Python 1.1, target SPARCstation/Solaris 2
        CLOS 18e (based on PCL September 16 92 PCL (f))
    * (shelf3--make)

    #<process 28098 :RUNNING>
    * (shelf3--add-fd-handler)

    #<Handler for INPUT on descriptor 9: #<Closure Over Function "DEFUN 
SHELF3--ADD-FD-HANDLER"
                                           {404113B1}>>
    * buffer => "Tryin"
    bytes-read => 5
    *expect-buffer* => "Tryin"

Why does registering the handler cause it to be invoked?

    * (sys:serve-event 1)
    NIL
    * (sys:serve-event 1)
    NIL

I would have expected SERVE-EVENT to notice that there is input
available on the descriptor and cause the registered handler to be
invoked.  But I know that the descriptor *is* ready for INPUT because
I can explicitly read from the stream.

    * (shelf3--read-5)
    g 127
    NIL
    * (shelf3--read-5)
    .0.0.
    NIL
    * (quit)

    % 

However, sometimes, the registered handler is suddenly called a bunch,
as if some clot broke free and suddenly it keeps getting called over
and over again.  Frequently, this degenerates to the following:

    Error in function COMMON-LISP::FD-STREAM-READ-N-BYTES:
       Error reading #<Stream for descriptor 9>: I/O error
    Error flushed ...
    0] 
    Error in function COMMON-LISP::FD-STREAM-READ-N-BYTES:
       Error reading #<Stream for descriptor 9>: I/O error
    Error flushed ...
    0] 
    Error in function COMMON-LISP::FD-STREAM-READ-N-BYTES:
       Error reading #<Stream for descriptor 9>: I/O error
    Error flushed ...
    0] 
    ^Z
    % kill %1

The only recourse at this point is to kill the process.


Reply via email to