On Tue, Sep 21, 2021 at 12:25 PM Ruediger Pluem <rpl...@apache.org> wrote:
>
> On 9/20/21 1:31 PM, Yann Ylavic wrote:
> >
> > For CONN_STATE_WRITE_COMPLETION + CONN_SENSE_WANT_READ we indeed reach
> > here and will POLLIN, then once readable we come back with
> > CONN_STATE_WRITE_COMPLETION + CONN_SENSE_DEFAULT so if pending != OK
> > we'll reach the below:
> >
> >         else if (ap_run_input_pending(c) == OK) {
> >             cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
> >             goto read_request;
> >         }
> >
> > and thus ap_run_process_connection() directly.
>
> Thanks for the pointer. But I guess the similar
>
>    else if (c->data_in_input_filters) {
>             cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
>             goto read_request;
>
> in 2.4.x does not give this to us as I think that c->data_in_input_filters is 
> not updated until we get here. Hence we probably
> need to fix this differently here.

Yes, possibly a speculative read of one byte on c->input_filters..

> >
> > What about this patch (attached)?
> > I tried to comment a bit the WRITE_COMPLETION_STATE too, because it's
> > not only about writing...
> >
> > +    /* CONN_STATE_WRITE_COMPLETION is a misnomer, this is actually the
> > +     * user driver polling state which can be POLLOUT but also POLLIN
> > +     * depending on cs->pub.sense. But even for CONN_SENSE_WANT_READ
> > +     * we want the outgoing pipe to be empty before POLLIN, so there
>
> Why do we need to empty the outgoing pipe first? It will automatically go 
> into blocking once it thinks that it is needed.

If we don't flush what we have retained we might be in a situation
where the remote is waiting for these data before sending us
something, and we'd deadlock.

> If not I
> think that we can start processing input in parallel. If this produces more 
> output that cannot be queued we get into blocking
> anyway. The only drawback of starting input processing again could be that if 
> the request we start processing is running for a
> long time the output will not be flushed further until new output was 
> produced. And I guess working on the same connection
> in two different threads would not be possible as the connection structure is 
> not thread safe.

I don't think we should ever have the same connection handled by
multiple threads, that's a can of worms where we'd have to synchronize
at some point and determine which packet arrived first. Packets need
to be handled in sequence, when a connection is handled by a worker
thread it should never be in the MPM's pollset at the same time (i.e.
possibly scheduled by/to another thread).

> >
> >      if (cs->pub.state == CONN_STATE_WRITE_COMPLETION) {
> > -        int pending = DECLINED;
> > +        int pending, want_read = 0;
> >
> > -        ap_update_child_status(cs->sbh, SERVER_BUSY_WRITE, NULL);
> > -
> > -        if (from_wc_q) {
> > -            from_wc_q = 0; /* one shot */
> > -            pending = ap_run_output_pending(c);
> > +        if (cs->pub.sense == CONN_SENSE_DEFAULT) {
> > +            /* If the user did not ask for READ or WRITE explicitely then
> > +             * we are in normal post request processing, i.e. busy write
> > +             * in the scoreboard.
> > +             */
> > +            ap_update_child_status(cs->sbh, SERVER_BUSY_WRITE, NULL);
> >          }
> > -        else if (ap_filter_should_yield(c->output_filters)) {
>
> Why no longer the ap_filter_should_yield(c->output_filters) approach when a 
> proccesing just before left us in write completion?

I just wanted to "show" in the patch that we'd better call
ap_run_output_pending() when CONN_SENSE_WANT_READ to avoid the POLLOUT
if we can flush just now. ap_filter_should_yield() is an optimization
which avoids running the output filters if we already ran them or
called ap_run_output_pending() just before, but it's not necessarily
the case when CONN_SENSE_WANT_READ is asked (I suppose).
Anyway, I think we should ap_run_output_pending() in more cases then
the current "from_wc_q" (so I removed this logic), the right test is
possibly something along "from_wc_q || want_read" or something, or we
can just let ap_filter_should_yield() as is and do the POLLOUT even if
writing is non-blocking already..


Regards;
Yann.

Reply via email to