Usage of the shadow field in ngx_buf_t?

Brian Pane brianp at brianp.net
Fri Dec 4 05:29:36 MSK 2009


On Thu, Dec 3, 2009 at 5:35 PM, agentzh <agentzh at gmail.com> wrote:

> On Fri, Dec 4, 2009 at 7:13 AM, Brian Pane <brianp at brianp.net> wrote:
> > A follow-up question: When a body filter is processing buffers that
> > were produced by the proxy module (i.e., buffers containing an HTTP
> response
> > from a back-end server), is it safe to discard those buffers?
>
> I think so :) My ngx_chunkin module's output body filter does
> something like that to simply disgard the contents of the 411 error
> page and I don't think an upstream module like ngx_proxy will have any
> difference here :)
>
> > Or is it necessary to
> > pass the buffers through to the standard filters?
>
> Then your client will probably see those stuffs sooner or later, which
> is certainly not what you want :)
>
> >  It's not clear to me
> > whether anything in the standard filter chain needs to see the buffers
> > containing the upstream response in order to do cleanup or flow control.
>
> No, at least according to my knowledge :) Cleanup and flow control
> usually happens in places like ngx_http_finalize_request, or a
> read/write event handler. A notable exception might be bufs with the
> temporary field set to 1. These bufs might need to be freed sooner
> rather than later, but they're usually allocated in the current
> request's pool anyway, it may not be a very big issue.
>

After an afternoon with gdb, I think I've found one dependency: before
throwing away the buffers, the body filter needs to set buf->pos=buf->last
for each one.  This is due to the code at line ~201 of
core/ngx_output_chain.c:

        last = ctx->output_filter(ctx->filter_ctx, out);

        if (last == NGX_ERROR || last == NGX_DONE) {
            return last;
        }

        ngx_chain_update_chains(&ctx->free, &ctx->busy, &out, ctx->tag);
        last_out = &out;

After the filter returns, that code still references the filter chain that
was
passed into the filter (the variable "out").  It looks like the event loop
in ngx_event_pipe_write_to_downstream counts up the unsent bytes in
this chain, where unsent for each buf is computed as buf->last - buf->pos.
I don't yet understand all the logic that follows, but the end result was
that
for large responses, I'd eventually cross a threshold where my filter kept
getting called over and over with no new data.

-Brian
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://nginx.org/pipermail/nginx-devel/attachments/20091203/09a1c7fc/attachment-0001.html>


More information about the nginx-devel mailing list