Subject: [clisp-list] read-line (clisp 2.30/woody)

From: Michael Koehne <[email-masked]>
Date: Wed Jan 15 18:45:03 2003

Moin Guru's,

  attached to this mail is my first Common Lisp programm *blush* and
  *uhm well* i did some EMACS/LISP before and i have some reason for
  choosing LISP as the implementation language.
  
  The code fails with related problems.

  - the input method of mucl client does not detect end-of-file.
    There will be a last :input on socket-status, when the client
    closes the connection. The following read() system call, should
    result in 0 or -1. That has to be interpreted as :eof or something
    like that in read-char and read-char-no-hang. So read-line can
    detect it. The :eof will be once raised as non-blocking input
    followed with read() result of -1, and later as an error OF THE
    select() system call.

  - There is a race condition, if the client closed its connection
    during 'tick' (asuming that tick may take longer) between the
    :input and :output socket-status querys. In this case, the
    following socket-status will result in :output (and not :error
    as expected), but a write-line will trigger a SIG_PIPE.
    The race condition could be solved, if the second socket-status
    queries :io and input, is processed before output (for a 2nd
    time) and the read-line end-of-file problem is solved.
    But: how to catch broken pipe signals, as the server should run,
    or is it better (implementation problem similar to Perl) to
    ignore the signal ?

  - Once a client dropped its connection a dead socket is in the
    readfds list. This will cause a socket-status :input to return
    immediate, but the dead socket is neither at :input (for reading
    :eof like the first time directly after client dropped its
    connection) and also not in :error state. Its just nil, so
    the timeout is never reached, and the process is running wild
    till next tick, where it will die with a SIG_PIPE.

  - The code will have to deal with nasty telnet protocols (IAC
    options and commands) are there any low level system-read or
    system-write commands, working more reliable in that context ?

  I've tried several ways to call read-line. e.g as
  (read-line stream nil :my-eof-symbol) but none of them showed
  any end of file condition. I at last tried to read the characters
  one by one - and suprisingly: The -1 from read() system call, is
  interpreted as #\Newline ? So i think i'm lost and hope that someone
  points me to the right place, where to patch read-char and read-line.

  If you want to try the code :

  - install the real read-line again
    g/^.multiple-value-bind/s/mucl-read-line/read-line/
  - start clisp interactive ([m-x]run-lisp)

    (load "mucl-stream")
    (progn
      (unless mucl-running (mucl-open (make-instance 'mucl-server)))
      (setf (mucl-time mucl-running) (truncate (get-internal-real-time) 1000000))
      (setf (mucl-tick mucl-running) (* (truncate (mucl-time mucl-running) 30) 30))
      (dotimes (i 100) (mucl-pulse mucl-running)) )

  - telnet localhost 5555, type something, and look about tick.
    close telnet connection.
  - investigate the clisp debuging output.

  *uh* yes i know lot of this code could/should be improved - PLEASE
  drop me a mail, if your eye catches something that me did plain wrong.

peace on your way,
  Michael

;;; mucl-stream MUCL - Multi User Common Lisp Stream Classes
;;; (c) GNU GPL 2003 

;;; debugging

(defvar mucl-demon nil "demon mode")
(defun mucl-debug (s) "write debug messages, if not in demon mode"
  (unless mucl-demon (write-line s)) nil)
(defvar mucl-running nil "the running MUCL server")

;;; class definitions

(defclass mucl-stream ()
  ((sock :accessor mucl-sock :initarg :sock))
  (:documentation "The basic MUCL stream class"))
(defclass mucl-server (mucl-stream)
  ((port :accessor mucl-port :initform 5555)
   (peer :accessor mucl-peer)
   (hash :accessor mucl-hash)
   (tick :accessor mucl-tick)
   (time :accessor mucl-time))
  (:documentation "The MUCL server stream class"))
(defclass mucl-client (mucl-stream)
  ((buff :accessor mucl-buff)
   (ique :accessor mucl-ique)
   (oque :accessor mucl-oque))
  (:documentation "The MUCL client stream class"))

;;; method definitions

(defgeneric mucl-open  (mucl-stream &optional port)
  (:documentation "Open the object"))
(defgeneric mucl-close (mucl-stream)
  (:documentation "Close the object"))
(defgeneric mucl-input (mucl-stream)
  (:documentation "Receive input"))
(defgeneric mucl-output (mucl-stream)
  (:documentation "Send output"))
(defgeneric mucl-error (mucl-stream)
  (:documentation "Process error"))
(defgeneric mucl-pulse (mucl-stream)
  (:documentation "Process pulse"))

;;; mucl-server implementation

(defmethod mucl-open ((self mucl-server) &optional port)
  (when port (setf (mucl-port self) port))
  (setf (mucl-sock self) (socket-server (mucl-port self)))
  (setf (mucl-peer self) nil)
  (setf (mucl-hash self) nil)
  (setq mucl-running self)
  (mucl-debug "MUCL server open") )
(defmethod mucl-close ((self mucl-server))
  (socket-server-close (mucl-sock self))
  (setf (mucl-sock self) nil)
  (setq mucl-running nil)
  (mucl-debug "MUCL server close") )
(defmethod mucl-input ((self mucl-server))
  (let ((p (make-instance 'mucl-client)))
    (mucl-open p (socket-accept (mucl-sock self)))
    (mucl-debug "MUCL server accept") ))
(defmethod mucl-output ((self mucl-server))
  (mucl-debug "MUCL server output error")
  (mucl-close self))
(defmethod mucl-error ((self mucl-server))
  (mucl-debug "MUCL server error")
  (mucl-close self))
(defmethod mucl-pulse ((self mucl-server))
  (let (socks stats time)
    (when mucl-running
      (setq socks (cons (mucl-sock self)
			(mapcar #'(lambda (s)
				    (cons (mucl-sock s) :input))
				(mucl-peer self)) ))
      (setq stats (socket-status socks 5 50000))
      (mucl-stream-loop socks stats) )
    (setq time (truncate (get-internal-real-time) 1000000))
    (when (>= time (mucl-tick self))
      (setf (mucl-tick self) (+ (mucl-tick self) 30))
      (mucl-debug (format nil "MUCL server tick ~A"
			  (mucl-date time) ))
      (let ((s (format nil "tick ~A~%" (mucl-date time)) ))
	(dolist (p (mucl-peer self)) (mucl-queue p s))))
    (when (and mucl-running (mucl-peer self))
      (setq socks (mapcar #'(lambda (s)
			      (cons (mucl-sock s) :output))
			  (mucl-peer self)) )
      (setq stats (socket-status socks 0 50000))
      (mucl-stream-loop socks stats) )))

;;; MUCL client method implementation

(defmethod mucl-open ((self mucl-client) &optional sock)
  (when sock
    (setf (mucl-oque self) nil)
    (setf (mucl-ique self) nil)
    (setf (mucl-buff self) nil)
    (setf (mucl-sock self) sock)
    (setf (mucl-hash mucl-running) nil)
    (push self (mucl-peer mucl-running))
    (mucl-debug "MUCL client open") ))
(defmethod mucl-close ((self mucl-client))
  (close (mucl-sock self))
  (setf (mucl-sock self) nil)
  (setf (mucl-hash mucl-running) nil)
  (delete self (mucl-peer mucl-running))
  (mucl-debug "MUCL client close") )
(defun mucl-read-line (stream)
  (let ((buffer (make-array 10 :element-type 'character
			    :adjustable t :fill-pointer 0)))
    (loop
     (let ((c (read-char stream)))
       (mucl-debug (format nil "[~A]" c))
       (cond ((not c)
	      (return (values nil t)))
	     ((eq c ':EOF)
	      (return (values (coerce buffer 'simple-string) t)))
	     ((eql c #\Newline)
	      (return (values (coerce buffer 'simple-string) nil)))
	     (t (vector-push-extend c buffer))
	     )))))
(defmethod mucl-input ((self mucl-client))
  (multiple-value-bind (l f) (mucl-read-line (mucl-sock self))
    (mucl-debug (format nil "MUCL process (~A|~A)~%" l f))
    (if (or f (not l))
	(mucl-close self)
      (mucl-debug (format nil "MUCL process (~A)~%" l)) )))
(defmethod mucl-output ((self mucl-client))
  (when (mucl-oque self)
    (write-string (car (mucl-oque self)) (mucl-sock self))
    (setf (mucl-oque self) (cdr (mucl-oque self))) ))
(defmethod mucl-error ((self mucl-client))
  (mucl-debug "MUCL client error")
  (mucl-close self) )
(defun mucl-queue (client string) "queue a string to send a client"
  (setf (mucl-oque client) (append (mucl-oque client) (list string))))

;;; control functions

(defun mucl-stream-loop (socks stats) "loop over socket status"
  (unless (mucl-hash mucl-running)
    (setf (mucl-hash mucl-running)
	  (cons
	   (cons (mucl-sock mucl-running) mucl-running)
	   (mapcar #'(lambda (s)
		       (cons (mucl-sock s) s))
		   (mucl-peer mucl-running)) )))
  (loop
   (unless (car socks) (return))
   (let ((csock (car socks))
	 (cstat (car stats))
	 cstream)
     (when (listp csock) (setq csock (car csock)))
     (setq cstream (cdr (assoc csock (mucl-hash mucl-running))))
     (format t "MUCL check ~A stat ~A~%" csock cstat)
     (if cstream
	 (case cstat
	   ((t :input) (mucl-input cstream))
	   (:output (mucl-output cstream))
	   (:error (mucl-error cstream))
	   (otherwise (when cstat
			(format t "MUCL error ~A stat ~A~%" csock cstat)
			(mucl-error cstream))))
	(format t "MUCL error no object ~A stat ~A hash ~A"
		csock cstat (mucl-hash mucl-running)) ))
   (unless (cdr socks) (return))
   (setq stats (cdr stats))
   (setq socks (cdr socks)) ))
(defun mucl-start () "start MUCL"
  (unless mucl-running (mucl-open (make-instance 'mucl-server)))
  (setf (mucl-time mucl-running) (truncate (get-internal-real-time) 1000000))
  (setf (mucl-tick mucl-running) (* (truncate (mucl-time mucl-running) 30) 30))
  (loop (unless mucl-running (return)) (mucl-pulse mucl-running)) )
(defun mucl-stop () "stop MUCL"
  (when mucl-running (mucl-close mucl-running)))
(defun mucl-date (time &optional shift) "traveller GAME time"
  (let (year date hour min)
    (setq year (truncate time 518400))
    (setq date (- (truncate time 1440) (* year 360)))
    (setq hour (- (truncate time 60) (+ (* year 360 24) (* date 24))))
    (setq min (- time (+ (* hour 60) (* year 518400) (* date 1440))))
    (when shift (setq year (+ year shift)))
    (setq str (format nil "~4D-~3,'0D ~2,'0D:~2,'0D" year date hour min))
    str))

; mailto:[email-masked]             UNA:+.? 'CED+2+:::Linux:2.4.6'UNZ+1'
; http://www.xml-edifact.org/           CETERUM CENSEO WINDOWS ESSE DELENDAM

---

From: Sam Steingold <[email-masked]>
Date: Fri Jan 17 12:05:21 2003

> * In message <[email-masked]>
> * On the subject of "[clisp-list] read-line (clisp 2.30/woody)"
> * Sent on Thu, 16 Jan 2003 03:44:43 +0100
> * Honorable Michael Koehne <[email-masked]> writes:
>

this is why most communications are done using a fixed protocol.
i.e., you close a connection only after declaring an intent to do so.
(TCP/IP gurus are welcome to refute this!)

>    (unless (car socks) (return))

you mean (unless socks) here!

>    (setq socks (cdr socks)) ))

what you want is probably

        (loop :for sock :in socks :for stat :in stats :do
          ...)

I really hope our resident network gurus will provide more information!

-- 
Sam Steingold (http://www.podval.org/~sds) running RedHat8 GNU/Linux
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html>
The program isn't debugged until the last user is dead.

---

From: Michael Koehne <[email-masked]>
Date: Fri Jan 17 16:10:06 2003

Moin Sam Steingold,

> (TCP/IP gurus are welcome to refute this!)

  well - as the mucl-date suggests, by running to fast at factor 60,
  the code should become the chat part of a multi-user-dungeon. Users
  in those telnet (like) games may drop the connection either by
  crashing their user client (some many of them are lisp based ;-) 
  or just but stop playing - and rebooting their Windoof.
  
  From a Perl point of view: ignore sigpipe, but provide error
  conditions for read-line, write-line and socket-status.

>         (loop :for sock :in socks :for stat :in stats :do

  *hm* i did'nt realise that its possible to run more than one list
  in a loop - this comes handy.

> I really hope our resident network gurus will provide more information!

  oups - i asumed that YOU are the network guru, from the view at
  port/net.lisp ;-)

  the problems with my code:
  - how to detect :eof with read-line (smells like a clisp 2.30 bug)
  - how to ignore (or catch) sig_pipe
  - how to improve socket-status to detect dead sockets.
  portability/reliabilty:
  - gcl does not provide something like socket-status (unix select call)
  - clisp does not have a system-write and system-read
  - cmu is totaly different

Bye Michael
-- 
  mailto:[email-masked]             UNA:+.? 'CED+2+:::Linux:2.4.6'UNZ+1'
  http://www.xml-edifact.org/           CETERUM CENSEO WINDOWS ESSE DELENDAM

---

From: Sam Steingold <[email-masked]>
Date: Fri Jan 17 16:46:02 2003

> * In message <[email-masked]>
> * On the subject of "Re: [clisp-list] read-line (clisp 2.30/woody)"
> * Sent on Sat, 18 Jan 2003 01:11:30 +0100
>   crashing their user client (some many of them are lisp based ;-) or
>   just but stop playing - and rebooting their Windoof.

in clisp:
> (setq o (socket-server 12345))

in bash:
$ telnet 15:14:06 sds@loiso:/usr/local/src/gcl/ansi-tests [56]$ telnet localhost 12345
Trying 127.0.0.1...
Connected to loiso (127.0.0.1).
Escape character is '^]'.
3456
^]

telnet> Connection closed.
$

back to clisp:

> (setq o (socket-accept s))
#<IO UNBUFFERED SOCKET-STREAM CHARACTER 0.0.0.0:12345>
> (read-line o nil :EOF)
"3456" ;
NIL
> (read-line o nil :EOF)
:EOF ;
T

no SIGPIPE.

>   - how to detect :eof with read-line (smells like a clisp 2.30 bug)

(READ-LINE stream NIL :EOF)

>   - how to ignore (or catch) sig_pipe

you should not get it (I think!)

>   - how to improve socket-status to detect dead sockets.

what is a dead socket? the one for which SOCKET-STATUS returns :ERROR?

--
Sam Steingold (http://www.podval.org/~sds) running RedHat8 GNU/Linux
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html>
If you try to fail, and succeed, which have you done?

---

From: Michael Koehne <[email-masked]>
Date: Sat Jan 18 06:34:03 2003

Moin Sam Steingold,

  lets investigate the problem a bit:

    [1]> (setq s (socket-server 12345))
    #<SOCKET-SERVER 0.0.0.0:12345>
    [2]> (setq o (socket-accept s))
    #<IO UNBUFFERED SOCKET-STREAM CHARACTER 0.0.0.0:12345>
    [3]> (read-line o nil :EOF)
    "asf" ;
    NIL
    [4]> (read-line o nil :EOF)
    :EOF ;
    T
    [5]> 

  this looks fine - but using a similar read-line in my program, does not
  detect :EOF. So lets investigate - by reducing my program to a minimal
  skeleton showing the situation :

    (progn
      (format t "waiting for connect~%")
      (setq serv (socket-server 5555))
      (setq sock (socket-accept serv))
      (format t "waiting for input~%")
      (dotimes (n 50)
        (setq stat (socket-status (list serv (cons sock :input)) 0 500000))
        (format t "Status ~A~%" stat)
        (when (eq (cadr stat) :INPUT)
          (multiple-value-bind (line flag) (read-line sock nil :EOF)
            (format t "Line: (~A) Flag:(~A)~%" line flag))))) 

  This will show the following missbehavior :

  - first line a client send looks ok

        Status (NIL INPUT)
        Line: (asdr aser) Flag:(NIL)
        Status (NIL NIL)

  - two :input events will be raised by socket-status the following
    times a telnet client types a line

        Status (NIL INPUT)
        Line: () Flag:(NIL)
        Status (NIL INPUT)
        Line: (ase 23) Flag:(NIL)
        Status (NIL NIL)

  - only one :input event will be raised, if the client closes the
    connections showing :

        Status (NIL INPUT)
        Line: () Flag:(NIL)
        Status (NIL NIL)

  - the following socket-status will return immediate ignoring timeout,
    because one of the sockets is dead. No :input or :error events are
    raised. The loop is running wild at 100% CPU load with:

        Status (NIL NIL)

  - One can call read-line by hand afterwards, to see, that the socket
    is at end-of-file :

      (multiple-value-bind (line flag) (read-line sock nil :EOF)
        (format t "Line: (~A) Flag:(~A)~%" line flag))

        Line: (EOF) Flag:(T)

  the questions now:

  where do the empty read-line's come from ? One idea could be that
  telnet is sending <CR><LF> - but the following progn does NOT show
  the named missbehavior - so its a side effect between socket-status
  and read-line, as the call of socket-status is the main difference
  between them.

    (progn
      (format t "waiting for connect~%")
      (setq serv (socket-server 5555))
      (setq sock (socket-accept serv))
      (format t "waiting for input~%")
      (loop
       (multiple-value-bind (line flag) (read-line sock nil :EOF)
         (format t "Line: (~A) Flag:(~A)~%" line flag)
         (when flag (return)) )))

> you should not get it (I think!)

  as told - the user will use some MUD client - they could always close
  quit or crash. So SIG_PIPE will be a common situation. The Perl way,
  would be to ignore SIG_PIPE, as the signal could interrupe any !LATER!
  system call. The EOF detection and :error condition on socket-status
  should be enough to sort those clients out and to close them !WITHOUT!
  lingering on the socket.

> what is a dead socket? the one for which SOCKET-STATUS returns :ERROR?

  a dead socket is one, where socket-status should return :error, but
  not yet does ;-(

  a dead socket is a file descriptor, that is already closed from
  the other side. This will cause the select system call to return
  failing immediate ignoring timeout, iirc. I'll try to compare some
  MUD c-code to socket-status in streams.d ;-)

Bye Michael

---

From: Sam Steingold <[email-masked]>
Date: Sat Jan 18 09:30:03 2003

> * In message <[email-masked]>
> * On the subject of "Re: read-line (clisp 2.30/woody)"
> * Sent on Sat, 18 Jan 2003 15:35:45 +0100
>   this looks fine - but using a similar read-line in my program, does
>   not detect :EOF.

Are you should you read the meaning of the second return value of
READ-LINE carefully?
it is non-nil only when the last line was not NL-terminated.

>     The loop is running wild at 100% CPU load with:
>         Status (NIL NIL)

I do not observe this on linux with the the latest CVS head.

>   as told - the user will use some MUD client - they could always
>   close quit or crash. So SIG_PIPE will be a common situation.

CLISP catches it.  you, the CLISP user, should not see it.

I must admit I am still not clear on what is your problem.
Sorry.

-- 
Sam Steingold (http://www.podval.org/~sds) running RedHat8 GNU/Linux
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html>
Old Age Comes at a Bad Time.

---

From: Michael Koehne <[email-masked]>
Date: Sat Jan 18 11:32:03 2003

Moin Sam Steingold,

> I do not observe this on linux with the the latest CVS head.

  i took that as a hint to try current CVS - source forge is under
  full load at saturday. So download took much longer than expected.

  'make' worked fine, but 'make check' failed with :

EQUAL-OK: "edcba"
(NREVERSE X) 
EQUAL-OK: "edcba"
X 
EQUAL-OK: "edcba"
(LET* ((X (MAKE-ARRAY 10 :FILL-POINTER 4 :ELEMENT-TYPE 'CHARACTER :INITIAL-ELEMENT #\Space :ADJUSTABLE T)) (Y (MAKE-ARRAY 10 :FILL-POINTER 4 :ELEMENT-TYPE 'CHARACTER :DISPLACED-TO X))) (ADJUST-ARRAY X '(5)) (CHAR Y 5)) 
EQL-OK: ERROR
(LET ((S (MAKE-ARRAY 10 :ELEMENT-TYPE 'CHARACTER :INITIAL-ELEMENT #\a)))
(LIST (MULTIPLE-VALUE-LIST (SYSTEM::STRING-INFO S)) (PROGN (SETF (AREF S 3) (CODE-CHAR 12345)) (MULTIPLE-VALUE-LIST (SYSTEM::STRING-INFO S)))
(PROGN (GC) (MULTIPLE-VALUE-LIST (SYSTEM::STRING-INFO S))) (PROGN (SETF (AREF S 3) (CODE-CHAR 123456)) (MULTIPLE-VALUE-LIST (SYSTEM::STRING-INFO S))) (PROGN (GC) (MULTIPLE-VALUE-LIST (SYSTEM::STRING-INFO S)))))
make[1]: *** [tests] Segmentation fault
make[1]: Leaving directory
`/bakunin/home/kraehe/AIlang/clisp-cvs/clisp/src/suite'
make: *** [testsuite] Error 2

  my environment: Debian/GNU/Linux (woody) DualPPro 250 / 128mb RAM.
  additional hints:

bakunin:~/AIlang/clisp-cvs/clisp/src $ uname -a
Linux bakunin.copyleft.de 2.4.18 #2 SMP Wed Oct 30 02:01:27 CET 2002 i686 unknown
bakunin:~/AIlang/clisp-cvs/clisp/src $ ulimit -a
core file size        (blocks, -c) 0
data seg size         (kbytes, -d) 98304
file size             (blocks, -f) unlimited
max locked memory     (kbytes, -l) 98304
max memory size       (kbytes, -m) 98304
open files                    (-n) 1024
pipe size          (512 bytes, -p) 8
stack size            (kbytes, -s) 8192
cpu time             (seconds, -t) unlimited
max user processes            (-u) 1024
virtual memory        (kbytes, -v) 98304
bakunin:~/AIlang/clisp-cvs/clisp/src $ ldd ./clisp
        libc.so.6 => /lib/libc.so.6 (0x4001b000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
bakunin:~/AIlang/clisp-cvs/clisp/src $ l /lib/libc.so.6 /lib/ld-linux.so.2
lrwxrwxrwx   11 Oct 16 13:22 /lib/ld-linux.so.2 -> ld-2.2.5.so
lrwxrwxrwx   13 Oct 16 13:22 /lib/libc.so.6 -> libc-2.2.5.so
bakunin:~/AIlang/clisp-cvs/clisp/src $ gzip < config.lisp > config.lisp.gz
bakunin:~/AIlang/clisp-cvs/clisp/src $ uuencode config.lisp.gz <config.lisp.gz
bakunin:~/AIlang/clisp-cvs/clisp/src $ ulimit -c unlimited
bakunin:~/AIlang/clisp-cvs/clisp/src $ make check
[ several lines deleted ]
bakunin:~/AIlang/clisp-cvs/clisp/src $ gdb ./lisp.run ./suite/core
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/libncurses.so.5...done.
Loaded symbols for /lib/libncurses.so.5
Reading symbols from /lib/libdl.so.2...done.
Loaded symbols for /lib/libdl.so.2
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
Reading symbols from /usr/lib/gconv/UTF-16.so...done.
Loaded symbols for /usr/lib/gconv/UTF-16.so
#0  0x0804ae23 in gc_mark ()
Breakpoint 1 at 0x8059dc8
Breakpoint 2 at 0x8058928
Breakpoint 3 at 0x8056d10
Breakpoint 4 at 0x804c67c
Breakpoint 5 at 0x804dfac
Breakpoint 6 at 0x804a9b0
Breakpoint 7 at 0x804aa14
Hardware watchpoint 8: {<data variable, no debug info>} 135720996
Num Type           Disp Enb Address    What
1   breakpoint     keep n   0x08059dc8 <funcall>
        zout fun
2   breakpoint     keep n   0x08058928 <apply>
        zout fun
3   breakpoint     keep n   0x08056d10 <eval>
        zout form
4   breakpoint     keep n   0x0804c67c <gar_col>
5   breakpoint     keep y   0x0804dfac <fehler_notreached>
6   breakpoint     keep y   0x0804a9b0 <SP_ueber>
7   breakpoint     keep y   0x0804aa14 <STACK_ueber>
8   hw watchpoint  keep n              
    {<data variable, no debug info>} 135720996
        p back_trace_out(0,0)
        continue
.gdbinit:88: Error in sourced command file:
Function "sigsegv_handler_failed" not defined.
(gdb) bt
#0  0x0804ae23 in gc_mark ()
#1  0x4017a378 in ?? ()
#2  0x0804c670 in do_gar_col ()
#3  0x0804c693 in gar_col ()
#4  0x68011c0b in ?? ()
#5  0x011d0300 in ?? ()
Cannot access memory at address 0x407e8
(gdb)

  i hope this helps.

Bye Michael
-- 
  mailto:[email-masked]             UNA:+.? 'CED+2+:::Linux:2.4.18'UNZ+1'
  http://www.xml-edifact.org/           CETERUM CENSEO WINDOWS ESSE DELENDAM

---

From: Sam Steingold <[email-masked]>
Date: Sat Jan 18 13:34:02 2003

> * In message <[email-masked]>
> * On the subject of "Re: Segmentation fault"
> * Sent on Sat, 18 Jan 2003 20:33:58 +0100

I know of this crash. it should not affect your case.

-- 
Sam Steingold (http://www.podval.org/~sds) running RedHat8 GNU/Linux
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html>
Never underestimate the power of stupid people in large groups.

---

From: Michael Koehne <[email-masked]>
Date: Sun Jan 19 08:51:04 2003

Moin Sam Steingold,

> it is non-nil only when the last line was not NL-terminated.

  after sleeping a night i realised that calling read-line in combination
  with socket-status is like using stdio with select(). So I think I need
  some low level (system-read stream array) and (system-write stream array)
  both returning an integer. I'll next read into ffi.

  Still read-line behaves funny, if called after socket-status. Except
  the first line, each line of telnet input will generate two :INPUT
  events on socket-status. The first one with "";NIL on read-line, the
  second one as "typed string";NIL. When the client closes its connection
  an :INPUT event will cause a read of "";NIL but there will never be
  a last :INPUT event. Instead socket-status will ignore its timeout.
  If calling read-line on the socket :EOF;t would be given, but this
  readline will be never called.

      (format t "waiting for connect")
      (setq serv (socket-server 5555))
      (setq sock (socket-accept serv))
      (format t "waiting for input")
      (dotimes (n 50)
        (setq stat (socket-status (list serv (cons sock :input)) 0 500000))
        (format t "Status ~A~%" stat)
        (when (eq (cadr stat) :INPUT)
          (multiple-value-bind (line flag) (read-line sock nil :EOF)
            (format t "Line: (~A) Flag:(~A)~%" line flag))))

  The question (beside that calling read-line in context of
  socket-status is a way to shoot oneself in the foot) is:
  
  where does the additional "";NIL results come from ?

> I do not observe this on linux with the the latest CVS head.

  The current CVS did not make a difference to plain 2.30 here.
  Btw: whats the best way to execute some clisp, that i dont want to
  install, because it crashes on regression test ?

> I must admit I am still not clear on what is your problem.

  have you tried the above code - is there some additional input ?
  at my site the above code clearly shows the situation.

Bye Michael