[usocket-devel] bug in backend/sbcl.lisp ?

I think the socket-connect function in the SBCL backend is incorrectly calling bind when creating a client stream socket. With the current code, when I create a lot of client stream sockets on a Linux system, the bind call in socket-connect eventually returns an error, address already in use. I don't think the bind call is needed for the client end of stream sockets. The following patch appears to fix the problem for me. bob --- backend/sbcl.lisp.~1~ 2011-09-23 13:46:55.071765010 -0400 +++ backend/sbcl.lisp 2011-09-23 13:51:33.841811680 -0400 @@ -269,9 +269,8 @@ :protocol (case protocol (:stream :tcp) (:datagram :udp)))) - (local-host (host-to-vector-quad (or local-host *wildcard-host*))) - (local-port (or local-port *auto-port*)) - usocket ok) + (usocket nil) + (ok nil)) (unwind-protect (progn (ecase protocol @@ -284,8 +283,6 @@ ;; 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) #+(and sbcl (not win32)) (labels ((connect ()

Robert Brown <robert.brown@gmail.com> writes:
With the current code, when I create a lot of client stream sockets on a Linux system, the bind call in socket-connect eventually returns an error, address already in use. I don't think the bind call is needed for the client end of stream sockets.
Bind is not needed unless we want a specific interface or a specific client port. USOCKET code seems to take /some/ care of not calling bind() unless it's needed; however, *wildcard-host* and *auto-port* being non-NIL makes bind() happen. (I guess that the underlying problem will go away if SO_REUSEADDR will be enabled on client socket, i.e. explicit bind() will succeed then). -- Regards, Anton Kovalenko +7(916)345-34-02 | Elektrostal' MO, Russia

On Fri, Sep 23, 2011 at 2:59 PM, Anton Kovalenko <anton@sw4me.com> wrote:> Bind is not needed unless we want a specific interface or a specific> client port. Seems like a better patch is the following, which calls bind if local-hostor local-port are specified in the call to socket-connect. --- third_party/lisp/usocket/backend/sbcl.lisp.~1~ 2011-08-12 16:23:26.718704693 -0400 +++ third_party/lisp/usocket/backend/sbcl.lisp 2011-09-23 15:11:24.481814325 -0400 @@ -269,9 +269,8 @@ :protocol (case protocol (:stream :tcp) (:datagram :udp)))) - (local-host (host-to-vector-quad (or local-host *wildcard-host*))) - (local-port (or local-port *auto-port*)) - usocket ok) + (usocket nil) + (ok nil)) (unwind-protect (progn (ecase protocol @@ -285,7 +284,9 @@ (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)) + (sb-bsd-sockets:socket-bind socket + (host-to-vector-quad (or local-host *wildcard-host*)) + (or local-port *auto-port*))) (with-mapped-conditions (usocket) #+sbcl (labels ((connect () @@ -306,8 +307,7 @@ (:datagram (when (or local-host local-port) (sb-bsd-sockets:socket-bind socket - (host-to-vector-quad - (or local-host *wildcard-host*)) + (host-to-vector-quad (or local-host *wildcard-host*)) (or local-port *auto-port*))) (setf usocket (make-datagram-socket socket)) (when (and host port)

Hi, Robert I'm sorry for replying your mail so late - a bit busy these days. Thanks, your patch fixed a bug in SOCKET-CONNECT: in my original design, if calling SOCKET-CONNECT without LOCAL-HOST and LOCAL-PORT keyword argument, the calling of bind() won't happen, but ... it seems that I calculate LOCAL-HOST / LOCAL-PORT too early, which caused the following protection block actually won't work: (when (or local-host local-port) ...) Any way, I've committed your fixes as r674. And consider this is a important fix, I'll make a new release as soon as possible. Besides, I agree Anton's opinion that the bind problem could be solved by enabling SO_REUSEADDR on client sockets, but I'm not sure if it's necessary to add another keyword argument to SOCKET-CONNECT ... when Robert's issue would be solved by current solutions. Regards, Chun Tian (binghe) 在 2011-9-24,03:20, Robert Brown 写道:
On Fri, Sep 23, 2011 at 2:59 PM, Anton Kovalenko <anton@sw4me.com> wrote:> Bind is not needed unless we want a specific interface or a specific> client port. Seems like a better patch is the following, which calls bind if local-hostor local-port are specified in the call to socket-connect. --- third_party/lisp/usocket/backend/sbcl.lisp.~1~ 2011-08-12 16:23:26.718704693 -0400 +++ third_party/lisp/usocket/backend/sbcl.lisp 2011-09-23 15:11:24.481814325 -0400 @@ -269,9 +269,8 @@ :protocol (case protocol (:stream :tcp) (:datagram :udp)))) - (local-host (host-to-vector-quad (or local-host *wildcard-host*))) - (local-port (or local-port *auto-port*)) - usocket ok) + (usocket nil) + (ok nil)) (unwind-protect (progn (ecase protocol @@ -285,7 +284,9 @@ (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)) + (sb-bsd-sockets:socket-bind socket + (host-to-vector-quad (or local-host *wildcard-host*)) + (or local-port *auto-port*))) (with-mapped-conditions (usocket) #+sbcl (labels ((connect () @@ -306,8 +307,7 @@ (:datagram (when (or local-host local-port) (sb-bsd-sockets:socket-bind socket - (host-to-vector-quad - (or local-host *wildcard-host*)) + (host-to-vector-quad (or local-host *wildcard-host*)) (or local-port *auto-port*))) (setf usocket (make-datagram-socket socket)) (when (and host port)
_______________________________________________ usocket-devel mailing list usocket-devel@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/usocket-devel
participants (3)
-
Anton Kovalenko
-
Chun Tian (binghe)
-
Robert Brown