Re: is there something wrong with www.scsh.net?

[email protected] Fri, 6 Jul 2007 20:27:49 -0700
Newsgroups gmane.lisp.scheme.scsh
Message-ID <[email protected]>
On Sat 21 Apr 2007 16:39, Eric Knauel <[email protected]> writes:

> scsh.net runs the SUnet web-server which sometimes gets into a stuck
> state and refuses to work.  There seems to be a bug somewhere in the
> code that deals with executing CGI programs.  However, we haven't
> found this bug yet...

It's not just CGI programs.  I'm seeing the same thing for surflets in
a personal application I'm running.  The problem occurs when scsh
spawns another scsh instance to do work.  The parent listens on its
end of the pipe, blocking for a response from the child:

    select(16, [15], [], [15], NULL)

per strace.  At the same time, the child process has called select in
a way that is guaranteed to block:

    select(0, [], [], [], NULL)

If the final parameter were a real struct timeval instead of NULL,
then this would block for that time duration and return.  But with a
NULL struct timeval and empty fdset arguments, this just blocks
forever (or until it gets some explicit interrupt, I suppose).

Looking at the code, the only select() call that seems to allow this
combination of parameters is in queue_ready_ports() in event.c.  A
combination of 'wait' being true, 'seconds' being -1, and 'pending'
being empty would trigger it:

  if ((! wait)
      &&  (pending.first == NULL))
    return (NO_ERRORS);
  FD_ZERO(&reads);
  FD_ZERO(&writes);
  FD_ZERO(&alls);
  limfd = 0;
  for (fdp = pending.first; fdp != NULL; fdp = fdp->next) {
    FD_SET(fdp->fd, fdp->is_input ? &reads : &writes);
    FD_SET(fdp->fd, &alls);
    if (limfd <= fdp->fd)
      limfd = fdp->fd + 1;
  }
  tvp = &tv;
  if (wait)
    if (seconds == -1){
      tvp = NULL;
    }
    else {
      tv.tv_sec = seconds;
      tv.tv_usec = ticks * (1000000 / TICKS_PER_SECOND);
    }
  else
    timerclear(&tv);

'wait' is true so we skip the return (NO_ERRORS).  'pending.first' is
NULL, so we don't hit any of the FD_SET calls.  And 'seconds' is -1 so
we set 'tvp' to NULL.  Then this call

    /* time gap */
    left = select(limfd, &reads, &writes, &alls, tvp);

has 0, [], [], [] and NULL.

Derek

-- 
Derek Upham
[email protected]