Current implementation has the following defects: * 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.
* In case of error, SB-BSD-SOCKETS:SOCKET-CLOSE was not being called with :ABORT T. * A unwind from SOCKET-CONNECT that didn't go through the handler leaked an FD. * An innocent non-error SIGNAL for any reason during SOCKET-CONNECT was taken to be a fatal error due to the handler on type T. * On datagram sockets CONNECTED-P wasn't set. Attached patch addresses these issues. Not deeply tested, though. Cheers, -- Nikodemus
Index: backend/sbcl.lisp =================================================================== --- backend/sbcl.lisp (revision 574) +++ backend/sbcl.lisp (working copy) @@ -199,6 +199,11 @@ (if usock-cond (signal usock-cond :socket socket)))))) +(defvar *dummy-stream* + (let ((stream (make-broadcast-stream))) + (close stream) + stream)) + (defun socket-connect (host port &key (protocol :stream) (element-type 'character) timeout deadline (nodelay t nodelay-specified) local-host local-port @@ -219,47 +224,53 @@ (let ((socket (make-instance 'sb-bsd-sockets:inet-socket :type protocol :protocol (case protocol - (:stream :tcp) - (:datagram :udp))))) - (handler-case - (ecase protocol - (:stream - (let* ((stream - (sb-bsd-sockets:socket-make-stream socket - :input t - :output t - :buffering :full - #+sbcl #+sbcl - :timeout timeout - :element-type element-type)) - ;;###FIXME: The above line probably needs an :external-format - (usocket (make-stream-socket :stream stream :socket socket)) - (ip (host-to-vector-quad host))) - ;; binghe: use SOCKOPT-TCP-NODELAY as internal symbol - ;; to pass compilation on ECL without it. - (when (and nodelay-specified sockopt-tcp-nodelay-p) - (setf (sb-bsd-sockets::sockopt-tcp-nodelay socket) nodelay)) - (when (or local-host local-port) - (sb-bsd-sockets:socket-bind socket - (host-to-vector-quad - (or local-host *wildcard-host*)) - (or local-port *auto-port*))) - (with-mapped-conditions (usocket) - (sb-bsd-sockets:socket-connect socket ip port)) - usocket)) - (:datagram - (when (or local-host local-port) - (sb-bsd-sockets:socket-bind socket - (host-to-vector-quad - (or local-host *wildcard-host*)) - (or local-port *auto-port*))) - (when (and host port) - (sb-bsd-sockets:socket-connect socket (host-to-vector-quad host) port)) - (make-datagram-socket socket))) - (t (c) - ;; Make sure we don't leak filedescriptors - (sb-bsd-sockets:socket-close socket) - (error c))))) + (:stream :tcp) + (:datagram :udp)))) + (ip (host-to-vector-quad host)) + (local-host (host-to-vector-quad (or local-host *wildcard-host*))) + (local-port (or local-port *auto-port*)) + usocket ok) + (unwind-protect + (progn + (ecase protocol + (:stream + ;; If make a real socket stream before the socket is + ;; connected, it gets a misleading name so supply a + ;; dummy value to start with. + (setf usocket (make-stream-socket :socket socket :stream *dummy-stream*)) + ;; binghe: use SOCKOPT-TCP-NODELAY as internal symbol + ;; to pass compilation on ECL without it. + (when (and nodelay-specified sockopt-tcp-nodelay-p) + (setf (sb-bsd-sockets::sockopt-tcp-nodelay socket) nodelay)) + (when (or local-host local-port) + (sb-bsd-sockets:socket-bind socket local-host local-port)) + (with-mapped-conditions (usocket) + (sb-bsd-sockets:socket-connect socket ip port) + ;; Now that we're connected make the stream. + (setf (socket-stream usocket) + (sb-bsd-sockets:socket-make-stream socket + :input t + :output t + :buffering :full + #+sbcl #+sbcl + :timeout timeout + :element-type element-type)))) + (:datagram + (when (or local-host local-port) + (sb-bsd-sockets:socket-bind socket + (host-to-vector-quad + (or local-host *wildcard-host*)) + (or local-port *auto-port*))) + (setf usocket (make-datagram-socket socket)) + (when (and host port) + (with-mapped-conditions (usocket) + (sb-bsd-sockets:socket-connect socket ip port) + (setf (connected-p usocket) t))))) + (setf ok t)) + ;; Clean up in case of an error. + (unless ok + (sb-bsd-sockets:socket-close socket :abort t))) + usocket)) (defun socket-listen (host port &key reuseaddress
_______________________________________________ usocket-devel mailing list usocket-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/usocket-devel