On Wed, Aug 10, 2022 at 09:45:44PM +0200, Omar Polo wrote:
> On 2022/08/10 15:07:15 +0200, Claudio Jeker wrote:
> > On Sun, Aug 07, 2022 at 11:10:22AM +0200, Omar Polo wrote:
> > > blob - ddf83f965d0e6a99ada695694bea77b775bae2aa
> > > blob + 1d577ba63efca388ca3644d1a52d9b3d9f246014
> > > --- usr.sbin/slowcgi/slowcgi.c
> > > +++ usr.sbin/slowcgi/slowcgi.c
> > > @@ -515,7 +515,34 @@ slowcgi_accept(int fd, short events, void *arg)
> > >  void
> > >  slowcgi_timeout(int fd, short events, void *arg)
> > >  {
> > > - cleanup_request((struct request*) arg);
> > > + struct request          *c;
> > > +
> > > + c = arg;
> > > +
> > > + if (c->script_flags & (STDOUT_DONE | STDERR_DONE | SCRIPT_DONE))
> > 
> > Is this the correct check? If we hit the timeout we want to close all
> > pipes to the CGI process and hope it dies because of that. Now one of
> > STDOUT_DONE or STDERR_DONE may have happened but the script is still
> > running.
> > 
> > I think it would be better to use:
> >         if (c->script_flags == (STDOUT_DONE | STDERR_DONE | SCRIPT_DONE))
> >                 return;
> > here.
> 
> Woops!  Yes, I meant to use == and not & here.
> 
> > Should slowcgi kill the command if SCRIPT_DONE is not set? 
> 
> RFC 3875 says that a script should be prepared to handle abnormal
> termination and tha the server acn interrupt or terminate it at any
> time and without warning, so killing the script is a possibility.
> 
> However, I'm a bit worried.  We could hit the timer not because of a
> faulty script but because an HTTP client is purposefully reading data
> slowly.  This could even allow to kill the scripts at specific points.
> Maybe I'm overthinking and it's not an issue.

The question I have is if scripts properly notice the IO error and
terminate. If a script got stuck somehow and just sits there it will not
realize it got killed. If that process exits at a later point slowcgi will
be confused about a spurious SIGCHLD.

What would happen if this instead sends a SIGTERM and after 5sec timeout a
SIGKILL to the process? It should result in a proper close of the session
via the usual channels (signal handler, io handler). Isn't that a better
way of handling a timeout?
 
> Anyway, here's an updated version of the diff for slowcgi with the
> fixed logic.
> 
> diff refs/remotes/origin/master refs/heads/wip
> commit - 3f5af05ce0a79edb8ab7606a968e2ff2617f1972
> commit + acc148801b858e3177b9b43a93d20fd53f97d40d
> blob - 9a0f8b5656d10fd09e62691a5ca827d357f1ff7a
> blob + 77e370c99d0d26646e699a285665f90323411444
> --- usr.sbin/slowcgi/slowcgi.c
> +++ usr.sbin/slowcgi/slowcgi.c
> @@ -515,7 +515,34 @@ slowcgi_accept(int fd, short events, void *arg)
>  void
>  slowcgi_timeout(int fd, short events, void *arg)
>  {
> -     cleanup_request((struct request*) arg);
> +     struct request          *c;
> +
> +     c = arg;
> +
> +     if (c->script_flags == (STDOUT_DONE | STDERR_DONE | SCRIPT_DONE))
> +             return;
> +
> +     if (!c->stdout_fd_closed) {
> +             c->stdout_fd_closed = 1;
> +             close(EVENT_FD(&c->script_ev));
> +             event_del(&c->script_ev);
> +     }
> +
> +     if (!c->stderr_fd_closed) {
> +             c->stderr_fd_closed = 1;
> +             close(EVENT_FD(&c->script_err_ev));
> +             event_del(&c->script_err_ev);
> +     }
> +
> +     if (!c->stdin_fd_closed) {
> +             c->stdin_fd_closed = 1;
> +             close(EVENT_FD(&c->script_stdin_ev));
> +             event_del(&c->script_stdin_ev);
> +     }
> +
> +     c->script_status = SIGALRM;
> +     c->script_flags = STDOUT_DONE | STDERR_DONE | SCRIPT_DONE;
> +     create_end_record(c);
>  }
>  
>  void
> 

-- 
:wq Claudio

Reply via email to