comparison src/http/ngx_http_request.c @ 5096:63014d919fec

Allocate request object from its own pool. Previously, it was allocated from a connection pool and was selectively freed for an idle keepalive connection. The goal is to put coupled things in one chunk of memory, and to simplify handling of request objects.
author Valentin Bartenev <vbart@nginx.com>
date Fri, 01 Mar 2013 14:55:42 +0000
parents 4fbef397c753
children d346adac0462
comparison
equal deleted inserted replaced
5095:4fbef397c753 5096:63014d919fec
363 363
364 364
365 static void 365 static void
366 ngx_http_init_request(ngx_event_t *rev) 366 ngx_http_init_request(ngx_event_t *rev)
367 { 367 {
368 ngx_pool_t *pool;
368 ngx_time_t *tp; 369 ngx_time_t *tp;
369 ngx_connection_t *c; 370 ngx_connection_t *c;
370 ngx_http_request_t *r; 371 ngx_http_request_t *r;
371 ngx_http_log_ctx_t *ctx; 372 ngx_http_log_ctx_t *ctx;
372 ngx_http_connection_t *hc; 373 ngx_http_connection_t *hc;
385 386
386 c->requests++; 387 c->requests++;
387 388
388 hc = c->data; 389 hc = c->data;
389 390
390 r = hc->request; 391 cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
391 392
392 if (r) { 393 pool = ngx_create_pool(cscf->request_pool_size, c->log);
393 ngx_memzero(r, sizeof(ngx_http_request_t)); 394 if (pool == NULL) {
394 395 ngx_http_close_connection(c);
395 r->pipeline = hc->pipeline; 396 return;
396 397 }
397 if (hc->nbusy) { 398
398 r->header_in = hc->busy[0]; 399 r = ngx_pcalloc(pool, sizeof(ngx_http_request_t));
399 } 400 if (r == NULL) {
400 401 ngx_destroy_pool(pool);
401 } else { 402 ngx_http_close_connection(c);
402 r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)); 403 return;
403 if (r == NULL) { 404 }
404 ngx_http_close_connection(c); 405
405 return; 406 r->pool = pool;
406 } 407
407 408 r->pipeline = hc->pipeline;
408 hc->request = r;
409 }
410 409
411 c->data = r; 410 c->data = r;
412 r->http_connection = hc; 411 r->http_connection = hc;
413 412
414 c->sent = 0; 413 c->sent = 0;
423 r->read_event_handler = ngx_http_block_reading; 422 r->read_event_handler = ngx_http_block_reading;
424 423
425 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 424 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
426 425
427 ngx_http_set_connection_log(r->connection, clcf->error_log); 426 ngx_http_set_connection_log(r->connection, clcf->error_log);
428
429 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
430 427
431 if (c->buffer == NULL) { 428 if (c->buffer == NULL) {
432 c->buffer = ngx_create_temp_buf(c->pool, 429 c->buffer = ngx_create_temp_buf(c->pool,
433 cscf->client_header_buffer_size); 430 cscf->client_header_buffer_size);
434 if (c->buffer == NULL) { 431 if (c->buffer == NULL) {
432 ngx_destroy_pool(r->pool);
435 ngx_http_close_connection(c); 433 ngx_http_close_connection(c);
436 return; 434 return;
437 } 435 }
438 } 436 }
439 437
440 if (r->header_in == NULL) { 438 r->header_in = hc->nbusy ? hc->busy[0] : c->buffer;
441 r->header_in = c->buffer;
442 }
443
444 r->pool = ngx_create_pool(cscf->request_pool_size, c->log);
445 if (r->pool == NULL) {
446 ngx_http_close_connection(c);
447 return;
448 }
449
450 439
451 if (ngx_list_init(&r->headers_out.headers, r->pool, 20, 440 if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
452 sizeof(ngx_table_elt_t)) 441 sizeof(ngx_table_elt_t))
453 != NGX_OK) 442 != NGX_OK)
454 { 443 {
2661 hc->busy[0] = b; 2650 hc->busy[0] = b;
2662 hc->nbusy = 1; 2651 hc->nbusy = 1;
2663 } 2652 }
2664 } 2653 }
2665 2654
2655 /* guard against recursive call from ngx_http_finalize_connection() */
2666 r->keepalive = 0; 2656 r->keepalive = 0;
2667 2657
2668 ngx_http_free_request(r, 0); 2658 ngx_http_free_request(r, 0);
2669 2659
2670 c->data = hc; 2660 c->data = hc;
2692 } 2682 }
2693 2683
2694 hc->pipeline = 0; 2684 hc->pipeline = 0;
2695 2685
2696 /* 2686 /*
2697 * To keep a memory footprint as small as possible for an idle 2687 * To keep a memory footprint as small as possible for an idle keepalive
2698 * keepalive connection we try to free the ngx_http_request_t and 2688 * connection we try to free c->buffer's memory if it was allocated outside
2699 * c->buffer's memory if they were allocated outside the c->pool. 2689 * the c->pool. The large header buffers are always allocated outside the
2700 * The large header buffers are always allocated outside the c->pool and 2690 * c->pool and are freed too.
2701 * are freed too.
2702 */ 2691 */
2703
2704 if (ngx_pfree(c->pool, r) == NGX_OK) {
2705 hc->request = NULL;
2706 }
2707 2692
2708 b = c->buffer; 2693 b = c->buffer;
2709 2694
2710 if (ngx_pfree(c->pool, b->start) == NGX_OK) { 2695 if (ngx_pfree(c->pool, b->start) == NGX_OK) {
2711 2696
3153 3138
3154 static void 3139 static void
3155 ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc) 3140 ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc)
3156 { 3141 {
3157 ngx_log_t *log; 3142 ngx_log_t *log;
3143 ngx_pool_t *pool;
3158 struct linger linger; 3144 struct linger linger;
3159 ngx_http_cleanup_t *cln; 3145 ngx_http_cleanup_t *cln;
3160 ngx_http_log_ctx_t *ctx; 3146 ngx_http_log_ctx_t *ctx;
3161 ngx_http_core_loc_conf_t *clcf; 3147 ngx_http_core_loc_conf_t *clcf;
3162 3148
3219 3205
3220 r->request_line.len = 0; 3206 r->request_line.len = 0;
3221 3207
3222 r->connection->destroyed = 1; 3208 r->connection->destroyed = 1;
3223 3209
3224 ngx_destroy_pool(r->pool); 3210 /*
3211 * Setting r->pool to NULL will increase probability to catch double close
3212 * of request since the request object is allocated from its own pool.
3213 */
3214
3215 pool = r->pool;
3216 r->pool = NULL;
3217
3218 ngx_destroy_pool(pool);
3225 } 3219 }
3226 3220
3227 3221
3228 static void 3222 static void
3229 ngx_http_log_request(ngx_http_request_t *r) 3223 ngx_http_log_request(ngx_http_request_t *r)