Dropped data on socket (stream) read

Bug #1721816 reported by Matthew Stickney on 2017-10-06
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
SBCL
Undecided
Unassigned

Bug Description

On Windows, if a client connects to a server, writes some data, and closes the socket, and the server writes some data after the socket has been closed, a subsequent read will fail to read the data and goes straight to EOF. This problem doesn't occur on Linux. CCL also exhibits this bug, so this is likely a Windows API quirk.

sbcl version: 1.3.9, 1.3.12 (a 1.4.0 build isn't available for windows)
Windows 7 SP1, 32-bit
*FEATURES*:
(:QUICKLISP :ASDF-PACKAGE-SYSTEM :ASDF3.1 :ASDF3 :ASDF2 :ASDF :OS-WINDOWS
 :NON-BASE-CHARS-EXIST-P :ASDF-UNICODE :ALIEN-CALLBACKS :ANSI-CL
 :ASH-RIGHT-VOPS :C-STACK-IS-CONTROL-STACK :COMMON-LISP :COMPARE-AND-SWAP-VOPS
 :CYCLE-COUNTER :FP-AND-PC-STANDARD-SAVE :GENCGC :IEEE-FLOATING-POINT
 :INLINE-CONSTANTS :LINKAGE-TABLE :LITTLE-ENDIAN :MEMORY-BARRIER-VOPS
 :MULTIPLY-HIGH-VOPS :OS-PROVIDES-DLOPEN :OS-PROVIDES-DLOPEN :OS-PROVIDES-PUTWC
 :PACKAGE-LOCAL-NICKNAMES :PRECISE-ARG-COUNT-ERROR :RAW-INSTANCE-INIT-VOPS
 :SB-DYNAMIC-CORE :SB-EVAL :SB-FUTEX :SB-LDB :SB-PACKAGE-LOCKS :SB-QSHOW
 :SB-SAFEPOINT :SB-SAFEPOINT-STRICTLY :SB-SOURCE-LOCATIONS :SB-TEST :SB-THREAD
 :SB-THRUPTION :SB-UNICODE :SB-WTIMER :SBCL :STACK-ALLOCATABLE-CLOSURES
 :STACK-ALLOCATABLE-FIXED-OBJECTS :STACK-ALLOCATABLE-LISTS
 :STACK-ALLOCATABLE-VECTORS :STACK-GROWS-DOWNWARD-NOT-UPWARD :SYMBOL-INFO-VOPS
 :UNWIND-TO-FRAME-AND-CALL-VOP :WIN32 :X86)

Test code -- call SBCL-READ-IT, then SBCL-WRITE-IT from a second process:

(defun sbcl-read-it ()
  (let ((srv-sock (make-instance 'sb-bsd-sockets:inet-socket :protocol :tcp :type :stream)))
    (sb-bsd-sockets:socket-bind srv-sock #(127 0 0 1) 9001)
    (sb-bsd-sockets:socket-listen srv-sock 5)
    (let* ((sock (sb-bsd-sockets:socket-accept srv-sock))
           (stream (sb-bsd-sockets:socket-make-stream sock :output t :input t :element-type '(unsigned-byte 8))))
      (unwind-protect
        (progn
          ;; Wait for the client to close the socket.
          (sleep 1)
          ;; If this write is commented out, everything works normally.
          (write-sequence (make-array 40 :initial-element 3 :element-type '(unsigned-byte 8)) stream)
          (finish-output stream)
          (let ((sequence (make-array 1 :element-type '(unsigned-byte 8))))
            ;; With the write above, this returns 0 bytes read; without it, reads a byte.
            (read-sequence sequence stream :end 1)))
      (sb-bsd-sockets:socket-close sock)
      (sb-bsd-sockets:socket-close srv-sock)))))

(defun sbcl-write-it ()
  (let ((sock (make-instance 'sb-bsd-sockets:inet-socket :protocol :tcp :type :stream)))
    (sb-bsd-sockets:socket-connect sock #(127 0 0 1) 9001)
    (unwind-protect
        (progn
          (let ((stream (sb-bsd-sockets:socket-make-stream sock :output t)))
            (format stream "Rhubarb")
            (finish-output stream)))
      (sb-bsd-sockets:socket-close sock))))

To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers