best approach for content phase handler to run again with event timer & ngx_done?

bsfranks at bsfranks at
Mon Jun 2 18:05:14 UTC 2014

Maxim - thank you for your helpful response.  I will review the memcached

In the meantime, I had tried a few things and ended up with the following
approach (as a rough example):

static ngx_int_t content_phase_handler(ngx_http_request_t *r) {
    /* some function that returns AGAIN or OK to either wait or proceed */
    rc = function();
    if (rc == NGX_AGAIN) {
        ctx->ev.handler = event_handler;
        ctx-> = r;
        ctx->ev.log = r->connection->log;
        ngx_add_timer(&ctx->ev, 100);
        return NGX_DONE;

    ...normal work of content phase handler...

static void event_handler(ngx_event_t *ev) {
    ngx_http_request *r;
    r = ev->data;
    r->write_event_handler = ngx_http_core_run_phases;

I had noticed from the DEBUG log output sequence that
nginx_finalize_request() was getting called after NGX_DONE was returned
from the content phase handler.  From the source, nginx_finalize_request()
called nginx_http_finalize_connection() if (r->main->count != 1), which
then called nginx_http_close_request() which decremented the count and
returned without freeing the req or closing the connection.

So, it seems like some of what you've recommended (incrementing req count,
and having finalize_request called) is then being done.

This seemed to work correctly and each time the event handler triggered,
the content phase handler was called again.  However, is calling
core_run_phases() a poor/dangerous approach or not recommended?

Also, is there a recommended lower bound for the millisecond timer?  For
example, don't make it smaller than X ms, otherwise the event cycle gets
run too frequently?



On Mon, Jun 2, 2014 at 9:26 AM, Maxim Dounin <mdounin at> wrote:

> Hello!
> On Fri, May 30, 2014 at 02:27:36PM -0700, bfranks781 at wrote:
> > If a content phase handler needs to wait on some potentially delayed
> > result, my understanding is that it should return NGX_DONE so that it is
> > called again.
> >
> > I've been reading through the eval, echo, and http_limit_req modules to
> see
> > how to integrate an nginx_add_timer event prior to returning NGX_DONE.  A
> > short timer event seems reasonable, because the content phase handler
> isn't
> > waiting on some other event type (subrequest result, timeout, etc).  The
> > timer event seems fairly straight-forward -- configure the event in a
> > request context and set the event handler, data and log.
> >
> > I don't really want my timer event handler to do anything -- rather I
> just
> > want the same content phase handler that had previously returned NGX_DONE
> > to run again.  In that case, should my timer event handler actually do
> > anything at all?  Is there a best practice for this -- i.e. have it point
> > to the write_event_handler(), call ngx_http_core_run_phases() or
> > ngx_http_run_posted_requests(), etc?
> A content phase handler will not be called again (or at least it's
> not supposed to).  If a content phase handler returns NGX_DONE, it
> means that it's responsible for further request handling, in
> particular:
> - you've already done proper request reference counting tweaks
>   (normally, by just calling ngx_http_read_client_request_body(),
>   which will do r->count++);
> - you are responsible for sending a response and then finalizing
>   the request with ngx_http_finalize_request().
> Modules based on the ngx_http_upstream.c (most simple one is
> memcached) are examples of content handlers which return NGX_DONE.
> --
> Maxim Dounin
> _______________________________________________
> nginx-devel mailing list
> nginx-devel at
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the nginx-devel mailing list