On Tue, Jul 05, 2022 at 10:08:53AM +0000, alex.vatche...@gmail.com wrote:
> >Synopsis:    httpd+slowcgi sometimes wrongly interpret next request
> >Category:    daemon
> >Environment:
>       System      : OpenBSD 7.1
>       Details     : OpenBSD 7.1 (GENERIC.MP) #3: Sun May 15 10:27:01 MDT 2022
>                        
> r...@syspatch-71-amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP
> 
>       Architecture: OpenBSD.amd64
>       Machine     : amd64
> >Description:
>       I've got web application OTOBO which is running on OpenBSD 
> httpd/slowcgi.
>       This application heavily uses AJAX.
>       Sometimes I'm able to reproduce the situation when httpd daemon passes
>       POST request to OTOBO script (via slowcgi) without POST data.
>       And the application stops in waiting to it and then times out.
>       After inspecting source code of httpd I've found the reason:
>       the http client context is reset after slowcgi closes the connection.
>       If the connection is not closed (httpd->slowcgi) and the client makes
>       new request using the same TCP connection (www client -> www server)
>       it httpd thinks that it already has got the request and headers.
> >Fix:
> diff --git a/usr.sbin/httpd/server_http.c b/usr.sbin/httpd/server_http.c
> index 63c91e8d075..def88331f16 100644
> --- a/usr.sbin/httpd/server_http.c
> +++ b/usr.sbin/httpd/server_http.c
> @@ -235,6 +235,20 @@ server_read_http(struct bufferevent *bev, void *arg)
>  
>       getmonotime(&clt->clt_tv_last);
>  
> +     if (clt->clt_fd != -1) {
> +             DPRINTF("%s: session %d: fcgi connection is active now",
> +                 __func__, clt->clt_id);
> +
> +             if (clt->clt_srvbev != NULL) {
> +                     bufferevent_free(clt->clt_srvbev);
> +                     clt->clt_srvbev = NULL;
> +             }
> +             close(clt->clt_fd);
> +             clt->clt_fd = -1;
> +             clt->clt_toread = TOREAD_HTTP_HEADER;
> +             server_reset_http(clt);
> +     }
> +
>       size = EVBUFFER_LENGTH(src);
>       DPRINTF("%s: session %d: size %lu, to read %lld",
>           __func__, clt->clt_id, size, clt->clt_toread);
> 
> 

I had a look at this and am fairly certain that this is not the right fix
for the issue at hand. It seems that persistent fcgi sessions are not
properly handled by httpd. The fcgi code should properly reset the clt
state at the end of a request. Also server_fcgi() should not always open
a new connection but that is a seperate issue. This is very similar to the
relayd problem with persitent backend connections. In both cases
persistent connections result in wrong internal state.

-- 
:wq Claudio

Reply via email to