CPS-chained subrequests with I/O interceptions no longer work in nginx 0.8.21 (Was Re: Custom event + timer regressions caused by the new release)

Maxim Dounin mdounin at mdounin.ru
Wed Oct 28 13:10:52 MSK 2009


On Wed, Oct 28, 2009 at 05:10:10PM +0800, agentzh wrote:

> On Wed, Oct 28, 2009 at 12:26 PM, agentzh <agentzh at gmail.com> wrote:
> > I'm guessing that nobody has done such things before, but I do believe
> > this is really useful for doing component-style programming in nginx,
> > because we don't have to rely on output filters (that are both costly
> > and *very* verbose to write) to hack in sequential subrequests.
> >
> Okay, folks, I've just created a git branch for my "echo" module and
> quickly hacked in the "classical" model of sequential subrequests by
> means of output filters.
> But again, 0.8.21 hangs the tests and passing every test if commenting
> out that line. 0.8.20 is still passing as before.
> The "classical" model looks like this:
> 1. The content handler issues a subrequest A, and registers a specific
> context object to the subrequest A. This context object could be
> recognized by a special output filter, say, F. And the current request
> object (ngx_http_request_t instance) associated with the main content
> handler is put into this context object.
> 2. The subrequest A generates outputs, chain by chain. And the F
> filter runs over them, chain by chain as well. The F filter detects if
> there's a context object attached to the current request object, if
> not, just calls the next body filter; if yes, walks through the
> current chain link to find out the last buf indicating the end of the
> currrent subrequest's response body stream.
> 3. If the last buf is found, the filter F takes the original request
> object that is associated with the original content handler from its
> context object, and initiates subrequests or do other things (actually
> this part is implemented as resuming the continuation of the content
> handler in the "echo" module).
> The tricky part is to search the "last buf" in the filter F which runs
> over the response body of a subrequest. It seems that buf->last_buf is
> already cleared by something else (more investigation needed) and
> buf->sync is set instead. So currently I'm cheating a bit and just
> checking the buf->sync flag and thinking it's the right way to do in
> at least late 0.8.x's. Well, it does not work in 0.7.x anyway.
> Thoughts?

Currently last_buf is only set for really last buffer.  I.e. 
subrequests shouldn't set it, if they do - it's a bug and likely 
to cause problems.

This isn't really natural (and I talked to Igor about this 
recently, probably this should be changed to simplify things), but 
that's how it works now.

> You can find the relevant source code here:
>    http://github.com/agentzh/echo-nginx-module/blob/master/src/location.c
> and here
>     http://github.com/agentzh/echo-nginx-module/blob/cps-filter/src/cps-filter.c
> where "cps_filter" is the codename for the filter F in the previous explanation.

One obvious error I see is that your code tries to do something 
once it passed buffer with last_buf set downstream.  This isn't 
going to work.

> Even though the "last buf" searching in subrequest output filter is
> still a hack, this experiment has convinced me that it looks more like
> a regression in nginx itself rather than misuse of the
> "post_subrequest" thingy or something else. In my cps-filter branch,
> I'm not using "post_subrequest" anyway.
> What do *you* think? ;)

You was asked to produce reduced code for reason.  Please do so.  
Your module is huge enough to be hard to analyse, and there are 
too many ways to screw things up.

Alternatively you may try to reproduce problem with SSI and/or 
addition filter.

Maxim Dounin

More information about the nginx mailing list