[Openmcl-devel] *multiprocessing-socket-io* and implications
Ralf Stoye
stoye at stoye.com
Mon Oct 29 06:10:27 PDT 2007
In August 2005 there was a discussion about ccl::*multiprocessing-
socket-io*.
After some tests i saw a performance benefit and better stability (no
need to handle eagain errors) from setting it to nil, but there is an
unlovely side-effect:
If you kill a process blocked by ccl:accept-connection the socket
stays open until the next connection arrives and after that, we have
an orphaned connection in state "CLOSE_WAIT" (seen with netstat). I
noticed the problem by using some http-server packages: Since they
kill their listening processes, none of them is able to stop and
restart the service when ccl::*multiprocessing-socket-io* is nil,
since the port is "already in use".
I got around this by modifying the "wait" clause in ccl::socket-
accept to resemble the behavior of the T clause (change socket
options to include #$O_NONBLOCK
before calling with-eagain... ) but i am not sure if this is the
"right" way to solve the problem.
Maybe someone can comment on this.
(i can post some code for testing if needed)
;; my modified socket-accept:
(defun socket-accept (fd wait socket)
(flet ((_accept (fd async)
(let ((res (c_accept fd (%null-ptr) (%null-ptr))))
(declare (fixnum res))
;; See the inscrutable note under ERROR HANDLING in
;; man accept(2). This is my best guess at what they mean...
(if (and async (< res 0)
(or (eql res (- #$ENETDOWN))
(eql res (- #+linux-target #$EPROTO
#+(or darwin-target freebsd-target) #$EPROTOTYPE))
(eql res (- #$ENOPROTOOPT))
(eql res (- #$EHOSTDOWN))
(eql res (- #+linux-target #$ENONET
#+(or darwin-target freebsd-target) #$ENETDOWN))
(eql res (- #$EHOSTUNREACH))
(eql res (- #$EOPNOTSUPP))
(eql res (- #$ENETUNREACH))))
(- #$EAGAIN)
res))))
(cond (wait
(let ((old (socket-call socket "fcntl" (fd-get-flags fd))))
(unwind-protect
(progn
(socket-call socket "fcntl" (fd-set-flags fd (logior old #
$O_NONBLOCK)))
(with-eagain fd :input
(_accept fd t)))
(socket-call socket "fcntl" (fd-set-flags fd old)))))
(*multiprocessing-socket-io*
(_accept fd t))
(t
(let ((old (socket-call socket "fcntl" (fd-get-flags fd))))
(unwind-protect
(progn
(socket-call socket "fcntl" (fd-set-flags fd (logior old #
$O_NONBLOCK)))
(_accept fd t))
(socket-call socket "fcntl" (fd-set-flags fd old))))))))
Greetings
Ralf Stoye
More information about the Openmcl-devel
mailing list