From 0c243146d694d8ebebc0939d1aaa798f6262bc9e Mon Sep 17 00:00:00 2001 From: Juho Snellman Date: Wed, 5 Apr 2006 06:24:10 +0000 Subject: [PATCH] 0.9.11.9: Changes to LISTEN for 0.9.11 caused it to sometimes return T even when reads on the stream could possibly block, due to overzealous updates of the FD-STREAM-LISTEN slot. Fix this, and rewrite the :LISTEN case in FD-STREAM-MISC-ROUTINE to be somewhat less convoluted. --- NEWS | 2 ++ src/code/fd-stream.lisp | 57 +++++++++++++++++++++++++---------------------- version.lisp-expr | 2 +- 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/NEWS b/NEWS index ea6333f..7257736 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,7 @@ ;;;; -*- coding: utf-8; -*- changes in sbcl-0.9.12 relative to sbcl-0.9.11: + * bug fix: LISTEN sometimes returned T even in cases where no data was + immediately available from the stream * fixed some bugs revealed by Paul Dietz' test suite: ** REMOVE-METHOD returns its generic function argument even when the method is not one of the generic functions' methods. diff --git a/src/code/fd-stream.lisp b/src/code/fd-stream.lisp index 9503594..5de405b 100644 --- a/src/code/fd-stream.lisp +++ b/src/code/fd-stream.lisp @@ -1582,33 +1582,36 @@ (declare (ignore arg2)) (case operation (:listen - (or (not (eql (fd-stream-ibuf-head fd-stream) - (fd-stream-ibuf-tail fd-stream))) - (fd-stream-listen fd-stream) - #!+win32 - (setf (fd-stream-listen fd-stream) - (sb!win32:fd-listen (fd-stream-fd fd-stream))) - #!-win32 - (setf (fd-stream-listen fd-stream) - (if (sysread-may-block-p fd-stream) - nil - ;; select(2) and CL:LISTEN have slightly different - ;; semantics. The former returns that an FD is - ;; readable when a read operation wouldn't block. - ;; That includes EOF. However, LISTEN must return - ;; NIL at EOF. - (progn (catch 'eof-input-catcher - ;; r-b/f too calls select, but it shouldn't - ;; block as long as read can return once w/o - ;; blocking - (refill-buffer/fd fd-stream)) - ;; If REFILL-BUFFER/FD set the FD-STREAM-LISTEN - ;; slot to a non-nil value (i.e. :EOF), keep - ;; that value. - (or (fd-stream-listen fd-stream) - ;; Otherwise we have data -> set the slot - ;; to T. - t)))))) + (labels ((do-listen () + (or (not (eql (fd-stream-ibuf-head fd-stream) + (fd-stream-ibuf-tail fd-stream))) + (fd-stream-listen fd-stream) + #!+win32 + (sb!win32:fd-listen (fd-stream-fd fd-stream)) + #!-win32 + ;; If the read can block, LISTEN will certainly return NIL. + (if (sysread-may-block-p fd-stream) + nil + ;; Otherwise select(2) and CL:LISTEN have slightly + ;; different semantics. The former returns that an FD + ;; is readable when a read operation wouldn't block. + ;; That includes EOF. However, LISTEN must return NIL + ;; at EOF. + (progn (catch 'eof-input-catcher + ;; r-b/f too calls select, but it shouldn't + ;; block as long as read can return once w/o + ;; blocking + (refill-buffer/fd fd-stream)) + ;; At this point either IBUF-HEAD != IBUF-TAIL + ;; and FD-STREAM-LISTEN is NIL, in which case + ;; we should return T, or IBUF-HEAD == + ;; IBUF-TAIL and FD-STREAM-LISTEN is :EOF, in + ;; which case we should return :EOF for this + ;; call and all future LISTEN call on this stream. + ;; Call ourselves again to determine which case + ;; applies. + (do-listen)))))) + (do-listen))) (:unread (setf (fd-stream-unread fd-stream) arg1) (setf (fd-stream-listen fd-stream) t)) diff --git a/version.lisp-expr b/version.lisp-expr index a0d7591..7d59ddd 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -17,4 +17,4 @@ ;;; checkins which aren't released. (And occasionally for internal ;;; versions, especially for internal versions off the main CVS ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".) -"0.9.11.8" +"0.9.11.9" -- 1.7.10.4