Writing a timer event (how to execute an event from time to time)

Peter Leonov gojpeg at gmail.com
Tue May 25 15:07:42 MSD 2010


Hi Rogério,

On 25.05.2010, at 9:16, Rogério Schneider <stockrt at gmail.com> wrote:

> Would you be kind enough to help me understanding how to write an
> event which executes itself from time to time, using Nginx event
> handler?
>
> I would like to register for each request a timer to execute a given
> task each 10 seconds.
>
> I am trying this in my module handler:
>
> static ngx_int_t ngx_http_hello_world_handler(ngx_http_request_t *r)
> {
>    ngx_buf_t    *b;
>    ngx_chain_t   out;
>    int           rc;
>    ngx_event_t     *wev;
>
>    wev = ngx_pcalloc(r->pool, sizeof(ngx_event_t));
>
>    if (wev == NULL) {
>        ngx_log_stderr(0, "wev null");
>        return NGX_ERROR;
>    }
>
>    wev->handler = ngx_http_hello_world_delay_handler;
>    wev->data = r;
>    wev->log = r->connection->log;
>
>    ngx_add_timer(wev, 10000);
>
>    r->headers_out.content_type.len = sizeof("text/plain") - 1;
>    r->headers_out.content_type.data = (u_char *) "text/plain";
>
>    b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
>
>    out.buf = b;
>    out.next = NULL;
>
>    b->pos = ngx_hello_world;
>    b->last = ngx_hello_world + sizeof(ngx_hello_world);
>    b->memory = 1;
>    b->flush = 1;
>    b->last_buf = 0;
>
>    r->headers_out.status = NGX_HTTP_OK;
>    r->headers_out.content_length_n = -1;
>
>    ngx_http_clear_content_length(r);
>    ngx_http_clear_accept_ranges(r);
>
>    ngx_http_send_header(r);
>
>    rc = ngx_http_output_filter(r, &out);
>
>    return rc; // never got reached due to b->last_buf=0 and chunked  
> response
> }
>
> and the delay handler:
>
> static void ngx_http_hello_world_delay_handler(ngx_event_t *ev)
> {
>    ngx_buf_t    *b;
>    ngx_chain_t   out;
>    int           rc;
>    ngx_connection_t        *c;
>    ngx_http_request_t      *r;
>
>    r = ev->data;
>    c = r->connection;
>
>    if (c->destroyed) {
>        return;
>    }
>
>    out.buf = b;
>    out.next = NULL;
>    b->pos = ngx_hello_world;
>    b->last = ngx_hello_world + sizeof(ngx_hello_world);
>    b->memory = 1;
>    b->flush = 1;
>    b->last_buf = 0;
>
>    rc = ngx_http_output_filter(r, &out);
>
>    return;
> }
>
> Do you think I am missing something? I still getting segfaults just as
> soon as my delay handler is called.
>
> Regards,
> -- 
> Rogério Schneider
> http://stockrt.github.com

In addition to the already said.

If only one timer per request is needed it is better to store it in  
the module context. Yesterday announced JavaScript module does exactly  
like this.

More to say, the timers mechanism is request agnostic. nginx doesn't  
track if the timer (wev) structure is already trashed, or even the  
entire request is freed. So you have to manage the lifetime of the  
timer manually.

JS module does it with a cleanup handler wich fires just at a time of  
a request destruction. Yep, think of it as a destructor.

In the clenup handler the module can check if the request has the  
module context, then just delete a timer with ngx_timer_del().

Even more to say. Developer needs to say to nginx that the request is  
referenced by a timer (there is no auto GC unfortunately). In the  
0.8.* series of nginx it could be done by incrementing the r->main- 
 >count. And do not forget to decrement it when the work with the  
request is finished. You may think of it as a reference counting (like  
in Perl). nginx 0.8.* is about to become a stable branch, so no risks  
here.

And of course take a look at the echo module, as well as at perl  
module, and JS module also might be of help.

Best regards,
Peter.


More information about the nginx-devel mailing list