Simple timeout module

I’m trying to build a simple timeout module using nginx timers. At the
beginning of a request I’m firing up a timer and after time interval
elapses
I want to check if request has already completed, and if not, finalize
it,
for example it with NGX_HTTP_REQUEST_TIME_OUT. I have created a filter
module. I’m creating a timer in filter headers:

static ngx_int_t simple_timeout_filter_headers(ngx_http_request_t*
request)
{
ngx_event_t* timeout_event;

timeout_event = ngx_pcalloc(request->pool, sizeof(ngx_event_t));
if (timeout_event == NULL)
{
return NGX_ERROR;
}

timeout_event->handler = simple_timeout_handler;
timeout_event->data = request;
timeout_event->log = request->connection->log;

ngx_log_debug0(NGX_LOG_DEBUG_HTTP, request->connection->log, 0,
“SIMPLE TIMEOUT TIMER START”);

ngx_add_timer(timeout_event, 3000); /* wait for 3 seconds */

return next_header_filter(request);
}

Simple timeout handler looks like this:

static void simple_timeout_handler(ngx_event_t* timeout_event)
{
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, timeout_event->log, 0,
“SIMPLE TIMEOUT TIMER END”);
}

And it works if I issue a request, and wait for a timer to fire. If I
issue
several requests while the previous timer is already in progress, I get
a
SEGFAULT.

A SEGFAULT happens here, while inserting a node into rbtree:

ngx_rbtree_insert() at ngx_rbtree.c:32 0x40d3c0
ngx_event_add_timer() at ngx_event_timer.h:84 0x42fc32
ngx_http_init_connection() at ngx_http_request.c:363 0x42fc32
ngx_event_accept() at ngx_event_accept.c:360 0x41c9ec
ngx_epoll_process_events() at ngx_epoll_module.c:822 0x424a00
ngx_process_events_and_timers() at ngx_event.c:248 0x41bb2c
ngx_single_process_cycle() at ngx_process_cycle.c:308 0x423c8b
main() at nginx.c:416 0x403bc6

So what I’m missing in my simple_timeout_filter_headers method?

Nginx version 1.8

Posted at Nginx Forum:

Hello!

On Wed, May 20, 2015 at 01:03:19PM -0400, donatasm wrote:

timeout_event = ngx_pcalloc(request->pool, sizeof(ngx_event_t));
“SIMPLE TIMEOUT TIMER START”);
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, timeout_event->log, 0,
“SIMPLE TIMEOUT TIMER END”);
}

And it works if I issue a request, and wait for a timer to fire. If I issue
several requests while the previous timer is already in progress, I get a
SEGFAULT.

At least you don’t remove the timer if the request completes
before the timer is triggered. This is enough to trigger a
segmentation fault.


Maxim D.
http://nginx.org/

On Wednesday 20 May 2015 13:03:19 donatasm wrote:

timeout_event = ngx_pcalloc(request->pool, sizeof(ngx_event_t));
“SIMPLE TIMEOUT TIMER START”);
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, timeout_event->log, 0,
ngx_event_add_timer() at ngx_event_timer.h:84 0x42fc32
Nginx version 1.8

You have allocated timer from a request memory pool. After the request
is
completed, the pool is freed, but you timer is still in the tree.

You should cleanup your timer.

wbr, Valentin V. Bartenev

Thanks, it worked as I added ngx_del_timer call in ngx_pool_cleanup_t
handler of a request

Posted at Nginx Forum: