[EMAIL PROTECTED] (Fabricio Chalub) writes:
> > someone has commented out the part that makes the socket use
> > nonblocking I/O.
>
> As a curiosity, from what I gather, CL-HTTP has two approaches for
> handling incoming connections: using MP:MAKE-PROCESS on
> tcp-interface-mp.lisp and using SERVE-EVENT ADD-FD-HANDLER on
> tcp-interface.lisp.  The files are conditionally chosen in sysdcl.lisp,
> based on #+MP. There seems to be a deliberate choice (in CL-HTTP, that
> is) of using multithreading with blocking IO vs. SERVE-EVENT with
> nonblocking IO there, since in one file the line is commented out and
> the other it isn't.
>
> So, out of curiosity, how does CMUCL's SERVE-EVENT compare to a
> multithreaded solution in this case (or maybe in a general case of event
> handling)?  Or you can't compare?  Or am I totally lost here? ;)

Your question made me realize how kludgy it is to use non-blocking I/O
here.  I think processes (threads) are supposed to make blocking I/O
calls; those calls are actually wrappers around an entry into the
scheduler, which turns the call into a non-blocking call and makes the
process that made the call wait until the non-blocking I/O completes.
I don't think CMUCL does this kind of thing yet.

Because it doesn't, if a process makes a blocking I/O call, it
actually blocks the whole CMUCL process at the operating system level
(as Tim Moore pointed out).

Looking more at the CL-HTTPD stream code for the mp version (in
tcp-stream-mp.lisp), it seems maybe non-blocking I/O is right.  This
code makes a call to unix-select, and it does a process-wait on the
fds.  It thus actually pretty much bypasses regular Lisp I/O
mechanisms.  So I guess setting the fd for non-blocking I/O, doing a
select, and then doing process-wait-until-fd-usable is right, given
the current state of things.  At least you don't wind up with a
busy-wait.

My goodness.  Looking at process-wait-until-fd-usable, it seems like
the select stuff in tcp-stream-mp might be redundant, because of the
following:

Code in process-wait-until-fd-usable:

(flet ((fd-usable-for-input ()
               (declare (optimize (speed 3) (safety 1)))
               (alien:with-alien ((read-fds (alien:struct unix:fd-set)))
                 (unix:fd-zero read-fds)
                 (unix:fd-set fd read-fds)
                 (multiple-value-bind (value err)
                     (unix:unix-fast-select
                      (1+ fd) (alien:addr read-fds) nil nil 0 0)
                   ;; Return true when input is available or there is
                   ;; an error other than an interrupt.
                   (and (not (eql value 0))
                        (or value (not (eql err unix:eintr)))))))

Code in tcp-stream-mp.lisp, function do-input:

    (multiple-value-bind
          (count errno)
        (alien:with-alien ((read-fds (alien:struct unix:fd-set)))
          (unix:fd-zero read-fds)
          (unix:fd-set fd read-fds)
          (unix:unix-fast-select (1+ fd) (alien:addr read-fds) nil nil 0 0))
      ;; Wait if input is not available or if interrupted.
      (when (or (eql count 0)
                (and (not count) (eql errno unix:eintr)))
        (unless (mp:process-wait-until-fd-usable
                 fd :input (http-stream-timeout stream))
          (error 'http-stream-timeout :function 'do-input :stream stream))))


So the call to process-wait-until-fd-usable re-does much of the same
stuff the code just did before it called it.

Oh well.

Can anyone say if my analysis above is correct, and setting the socket
for non-blocking I/O is the right thing?  And whether or not the
selects in tcp-stream-mp are necessary?

-- 
Fred Gilham                     [EMAIL PROTECTED]
"In the 20th century, more citizens were killed by their own
governments than by foreign enemies....totalitarianism first of all
regards its own people as the enemy." --- Arnold Beichman

Reply via email to