[Openmcl-devel] *multiprocessing-socket-io*

Gary Byers gb at clozure.com
Mon Mar 10 08:03:42 PDT 2008

If a thread is blocked in #_accept on a blocking socket in 1.1, I'm
not sure that the thread can be killed by PROCESS-KILL.  (Driving
a wooden stake through the heart of the thread may work ...)  This
has to do with the fact that many blocking system calls are automatically
restarted when the signal used by PROCESS-INTERRUPT is received.

The good news about that is that code which calls those blocking
system calls doesn't have to check to see if an "interrupted system
call" error (#$EINTR) occurred and manually retry the call.  The bad
news is that when the handler for the interrupt signal is established
with the SA_RESTART flag (as was the case in 1.1 and earlier), some
system calls (including #_accept) will be automatically restarted
and lisp won't regain control (and process the pending interrupt
request) until #_accept returns "normally."

When the socket's non-blocking, we don't generally block in
#_accept (but instead wait interruptibly for input to be available);
if PROCESS-KILL calls PROCESS-INTERRUPT to tell the thread to
kill itself, the interruptible wait completes and as it's returning
to lisp it handles the interrupt request and starts to kill itself.

Just to see if I'm on the right track here, could you check to
see if the thread is still around (quite possibly still blocked
in #_accept) when the listener socket is blocking and PROCESS-KILL
thinks that it's just killed the blocked thread ?

If this (#_accept not getting interrupted) is the root of the
problem, then the best thing to do in the short term is to 
make the socket non-blocking (by leaving *multiprocessing-socket-io*
set to T).  1.2 doesn't make blocking system calls automatically
restartable and is supposed to check each such system call for
#$EINTR and manually restart it when that value is returned.

On Mon, 10 Mar 2008, Ralf Stoye wrote:

> Hi,
> i think my post from 29. Oktober 2007 ("*multiprocessing-socket-io*
> and implications") either has been overlooked,
> or didn't made sense for anyone, i'll repeat it here, maybe someone
> can comment on it.
> Setting  ccl::*multiprocessing-socket-io* to nil provides some benefits
> (see mail from Gary Byers from 13. Mai 2005 14:29:32 MESZ),
> but it is problematic in connection with threads which are blocked
> during ccl:accept-connection:
> If you kill a process blocked by ccl:accept-connection the socket
> stays open (read: is not closed even when closed in an unwind-protect
> form)
> until the next connection arrives and even 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" (caused by the unclosed socket).
> 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 shure this isn't the right way.
> Here is a typical "usecase" from hunchentoot, running a
> (listening-)process with the following code:
> (unwind-protect
>      (progn
>        (setf socket (ccl:make-socket ...))
>        (loop (funcall function (ccl:accept-connection socket :wait
> t))))
>   (when socket
>     (cl:ignore-errors (close socket))))
> I have little to no experience writing socket-code on a lower level
> and i think that i have two conflicting demands:
>   a) let the thread block on this socket operation (on a system layer)
>   b) be able to kill this process and close the socket
> so maybe i can state a more concrete question:
> Is there any way to close a socket, when its thread is blocked during
> ccl:accept-connection (really in socket-accept),
> assuming  ccl::*multiprocessing-socket-io*  is nil.
> Or is it possible to change the socketoptions when a connection
> arrives (make it blocking?)
> Sure there is a very easy solution: let *multiprocessing-socket-io* be
> T,
> but i think this isn't "The Right Thing" either.
> Thanks,
> Ralf Stoye
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> http://clozure.com/mailman/listinfo/openmcl-devel

More information about the Openmcl-devel mailing list