Hi, I tried to fix this problem and now got correct behavior, but I'm not sure that I do correct solution :)

Can we fix `read-char-no-hang' bug with something like this?

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; in code/win32.lisp

;; FIXME: WSAEVENT = handle?

(define-alien-routine ("WSACreateEvent" wsa-create-event) handle)

(define-alien-routine ("WSAEventSelect" wsa-event-select) int
  (socket handle)
  (event-object handle)
  (network-events long))

;;; Listen for input on a Windows file handle.  Unlike UNIX, there
;;; isn't a unified interface to do this---we have to know what sort
;;; of handle we have.  Of course, there's no way to actually
;;; introspect it, so we have to try various things until we find
;;; something that works.  Returns true if there could be input
;;; available, or false if there is not.
(defun handle-listen (handle)
  (with-alien ((avail dword)
               (buf (array char #.input-record-size)))
    (unless (zerop (peek-named-pipe handle nil 0 nil (addr avail) nil))
      (return-from handle-listen (plusp avail)))

    (unless (zerop (peek-console-input handle
                                       (cast buf (* t))
                                       input-record-size (addr avail)))
      (return-from handle-listen (plusp avail)))

    ;; set third argument - bit mask instead 0 - something like FD_ACCEPT | ...
    (when (zerop (wsa-event-select handle (wsa-create-event) 0))
      (return-from handle-listen (plusp avail)))

    t))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

And then we have:

1)

(read-char-no-hang (make-string-input-stream "foo")) ;=> #\f

2)

(read-char-no-hang
 (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)
   (unwind-protect
    (sb-bsd-sockets:socket-make-stream
     (sb-bsd-sockets:socket-accept socket)
     :output t :input t :element-type 'character)
     (sb-bsd-sockets:socket-close socket))))

$ telnet localhost 5000

;=> Returns NIL immediately.