[usocket-cvs] r588 - usocket/branches/0.5.x/backend
Chun Tian (binghe)
ctian at common-lisp.net
Tue Mar 22 01:46:46 UTC 2011
Author: ctian
Date: Mon Mar 21 21:46:46 2011
New Revision: 588
Log:
Fixes for "SBCL/Win32: finalizer problem, etc", by Anton Kovalenko <anton at sw4me.com>
Modified:
usocket/branches/0.5.x/backend/sbcl.lisp
Modified: usocket/branches/0.5.x/backend/sbcl.lisp
==============================================================================
--- usocket/branches/0.5.x/backend/sbcl.lisp (original)
+++ usocket/branches/0.5.x/backend/sbcl.lisp Mon Mar 21 21:46:46 2011
@@ -199,6 +199,10 @@
(if usock-cond
(signal usock-cond :socket socket))))))
+;;; "The socket stream ends up with a bogus name as it is created before
+;;; the socket is connected, making things harder to debug than they need
+;;; to be." -- Nikodemus Siivola <nikodemus at random-state.net>
+
(defvar *dummy-stream*
(let ((stream (make-broadcast-stream)))
(close stream)
@@ -291,16 +295,29 @@
(sb-bsd-sockets:socket-close sock)
(error c)))))
+;;; "2. SB-BSD-SOCKETS:SOCKET-ACCEPT method returns NIL for EAGAIN/EINTR,
+;;; instead of raising a condition. It's always possible for
+;;; SOCKET-ACCEPT on non-blocking socket to fail, even after the socket
+;;; was detected to be ready: connection might be reset, for example.
+;;;
+;;; "I had to redefine SOCKET-ACCEPT method of STREAM-SERVER-USOCKET to
+;;; handle this situation. Here is the redefinition:" -- Anton Kovalenko <anton at sw4me.com>
+
(defmethod socket-accept ((socket stream-server-usocket) &key element-type)
(with-mapped-conditions (socket)
- (let ((sock (sb-bsd-sockets:socket-accept (socket socket))))
- (make-stream-socket
- :socket sock
- :stream (sb-bsd-sockets:socket-make-stream
- sock
- :input t :output t :buffering :full
- :element-type (or element-type
- (element-type socket)))))))
+ (let ((sock (sb-bsd-sockets:socket-accept (socket socket))))
+ (if sock
+ (make-stream-socket
+ :socket sock
+ :stream (sb-bsd-sockets:socket-make-stream
+ sock
+ :input t :output t :buffering :full
+ :element-type (or element-type
+ (element-type socket))))
+
+ ;; next time wait for event again if we had EAGAIN/EINTR
+ ;; or else we'd enter a tight loop of failed accepts
+ (setf (%ready-p socket) nil)))))
;; Sockets and their associated streams are modelled as
;; different objects. Be sure to close the stream (which
@@ -448,7 +465,15 @@
#+(and sbcl win32)
(progn
- (sb-alien:define-alien-type ws-socket sb-alien:unsigned-int)
+ ;; "SOCKET is defined as intptr_t in Windows headers; however, WS-SOCKET
+ ;; is defined as unsigned-int, i.e. 32-bit even on 64-bit platform. It
+ ;; seems to be a good thing to redefine WS-SOCKET as SB-ALIEN:SIGNED,
+ ;; which is always machine word-sized (exactly as intptr_t;
+ ;; N.B. as of Windows/x64, long and signed-long are 32-bit, and thus not
+ ;; enough -- potentially)."
+ ;; -- Anton Kovalenko <anton at sw4me.com>, Mar 22, 2011
+ (sb-alien:define-alien-type ws-socket sb-alien:signed)
+
(sb-alien:define-alien-type ws-dword sb-alien:unsigned-long)
(sb-alien:define-alien-type ws-event sb-alien::hinstance)
@@ -556,13 +581,33 @@
(defun (setf os-wait-list-%wait) (value wait-list)
(setf (sb-alien:deref (wait-list-%wait wait-list)) value))
+ ;; "Event handles are leaking in current SBCL backend implementation,
+ ;; because of SBCL-unfriendly usage of finalizers.
+ ;;
+ ;; "SBCL never calls a finalizer that closes over a finalized object: a
+ ;; reference from that closure prevents its collection forever. That's
+ ;; the case with USOCKET in %SETUP-WAIT-LIST.
+ ;;
+ ;; "I use the following redefinition of %SETUP-WAIT-LIST:
+ ;;
+ ;; "Of course it may be rewritten with more clarity, but you can see the
+ ;; core idea: I'm closing over those components of WAIT-LIST that I need
+ ;; for finalization, not the wait-list itself. With the original
+ ;; %SETUP-WAIT-LIST, hunchentoot stops working after ~100k accepted
+ ;; connections; it doesn't happen with redefined %SETUP-WAIT-LIST."
+ ;;
+ ;; -- Anton Kovalenko <anton at sw4me.com>, Mar 22, 2011
+
(defun %setup-wait-list (wait-list)
(setf (wait-list-%wait wait-list) (sb-alien:make-alien ws-event))
(setf (os-wait-list-%wait wait-list) (wsa-event-create))
(sb-ext:finalize wait-list
- #'(lambda () (unless (null (wait-list-%wait wait-list))
- (wsa-event-close (os-wait-list-%wait wait-list))
- (sb-alien:free-alien (wait-list-%wait wait-list))))))
+ (let ((event-handle (os-wait-list-%wait wait-list))
+ (alien (wait-list-%wait wait-list)))
+ #'(lambda ()
+ (wsa-event-close event-handle)
+ (unless (null alien)
+ (sb-alien:free-alien alien))))))
(defun %add-waiter (wait-list waiter)
(let ((events (etypecase waiter
More information about the usocket-cvs
mailing list