On Fri, Jan 21, 2022 at 1:09 AM <minf...@apache.org> wrote:
>
> Author: minfrin
> Date: Fri Jan 21 00:09:24 2022
> New Revision: 1897281
>
> URL: http://svn.apache.org/viewvc?rev=1897281&view=rev
> Log:
> event: Add support for non blocking behaviour in the
> CONN_STATE_READ_REQUEST_LINE phase, in addition to the existing
> CONN_STATE_WRITE_COMPLETION phase. Update mod_ssl to perform non blocking
> TLS handshakes.

It looks like reusing CONN_STATE_READ_REQUEST_LINE for that is causing
issues, see below.

> --- httpd/httpd/trunk/modules/ssl/mod_ssl.c (original)
> +++ httpd/httpd/trunk/modules/ssl/mod_ssl.c Fri Jan 21 00:09:24 2022
> @@ -691,6 +692,8 @@ static int ssl_hook_process_connection(c
>  {
>      SSLConnRec *sslconn = myConnConfig(c);
>
> +    int status = DECLINED;
> +
>      if (sslconn && !sslconn->disabled) {
>          /* On an active SSL connection, let the input filters initialize
>           * themselves which triggers the handshake, which again triggers
> @@ -698,13 +701,48 @@ static int ssl_hook_process_connection(c
>           */
>          apr_bucket_brigade* temp;
>
> +        int async_mpm = 0;
> +
>          temp = apr_brigade_create(c->pool, c->bucket_alloc);
> -        ap_get_brigade(c->input_filters, temp,
> -                       AP_MODE_INIT, APR_BLOCK_READ, 0);
> +
> +        if (ap_mpm_query(AP_MPMQ_IS_ASYNC, &async_mpm) != APR_SUCCESS) {
> +            async_mpm = 0;
> +        }
> +
> +        if (async_mpm) {
> +
> +            /* Take advantage of an async MPM. If we see an EAGAIN,
> +             * loop round and don't block.
> +             */
> +            apr_status_t rv;
> +
> +            rv = ap_get_brigade(c->input_filters, temp,
> +                           AP_MODE_INIT, APR_NONBLOCK_READ, 0);
> +
> +            if (rv == APR_SUCCESS) {
> +                /* great news, lets continue */
> +                status = DECLINED;
> +            }
> +            else if (rv == APR_EAGAIN) {
> +                /* we've been asked to come around again, don't block */
> +                status = OK;

Maybe we could return SUSPENDED here to tell the MPM that it should
call run_process_connection() again after poll()ing.

> +            }
> +            else {
> +                /* we failed, give up */
> +                status = DONE;
> +
> +                c->aborted = 1;
> +            }
> +        }
> +        else {
> +            ap_get_brigade(c->input_filters, temp,
> +                           AP_MODE_INIT, APR_BLOCK_READ, 0);
> +        }
> +
>          apr_brigade_destroy(temp);
>      }
> -
> -    return DECLINED;
> +
> +    return status;
>  }

> --- httpd/httpd/trunk/server/mpm/event/event.c (original)
> +++ httpd/httpd/trunk/server/mpm/event/event.c Fri Jan 21 00:09:24 2022
> @@ -1142,6 +1145,7 @@ read_request:
>       */
>      if (rc != OK || (cs->pub.state >= CONN_STATE_NUM)
>                   || (cs->pub.state < CONN_STATE_LINGER
> +                     && cs->pub.state != CONN_STATE_READ_REQUEST_LINE
>                       && cs->pub.state != CONN_STATE_WRITE_COMPLETION
>                       && cs->pub.state != 
> CONN_STATE_CHECK_REQUEST_LINE_READABLE
>                       && cs->pub.state != CONN_STATE_SUSPENDED)) {

The issue is that we've never asked process_connection hooks that
don't care about async and co to change cs->pub.state when they are
done, and for instance mod_echo's process_echo_connection() will
consume the whole connection but leave CONN_STATE_READ_REQUEST_LINE as
is, and here we'll no longer turn it to CONN_STATE_LINGER to close the
connection as before hence loop indefinitely between mod_echo and
mpm_event (eating a CPU) for a connection that is EOF already.

That's why I'm proposing above that ssl_hook_process_connection()
returns SUSPENDED and that we handle it as keep calling
run_process_connection() after poll()ing here in the MPM. Or have a
new CONN_STATE_WAIT_IO or something set by the hooks, though since we
have SUSPENDED already it looks unnecessary.


> @@ -1153,6 +1157,41 @@ read_request:
>          cs->pub.state = CONN_STATE_LINGER;
>      }


Regards;
Yann.

Reply via email to