@@ -493,30 +493,21 @@ void wakeup_event_handler(ngx_event_t *ev) {
493
493
" wakeup_event_handler called: %V%V" ,
494
494
&http_connection->host_header , &http_connection->url_path );
495
495
496
- // Move all pointers to the local variables because once we destroy the
497
- // pools we can no longer access the memory.
498
-
499
496
// Request and a connection pools.
500
- ngx_pool_t *rp = http_connection->request ->pool ;
501
- ngx_pool_t *cp = http_connection->connection .pool ;
497
+ ngx_pool_t *ep = http_connection->esp_pool ;
498
+ ngx_pool_t *cp = http_connection->connection_pool_reset .pool ;
499
+ ngx_pool_t *rp = http_connection->request_pool_reset .pool ;
502
500
503
- ngx_log_debug2 (NGX_LOG_DEBUG_HTTP, ev->log , 0 ,
504
- " esp: destroying pools c=%p, r=%p" , cp, rp);
505
-
506
- // If the connection is reset by peer, somehow rp or cp is 0.
507
- // Not sure if any of pools have been freed. But trying to free
508
- // a nullptr pool definitely will cause crash.
509
- // Here, choose the least of evil, memory leak over crash.
510
- if (rp == nullptr || cp == nullptr ) {
511
- ngx_log_debug2 (NGX_LOG_DEBUG_HTTP, ev->log , 0 ,
512
- " esp memory pools may not be freed: pools c=%p, r=%p" , cp,
513
- rp);
514
- return ;
515
- }
501
+ ngx_log_debug3 (NGX_LOG_DEBUG_HTTP, ev->log , 0 ,
502
+ " esp: destroying pools ep=%p, cp=%p, rp=%p" , ep, cp, rp);
516
503
517
- // Destroy the pools.
518
- ngx_destroy_pool (rp);
519
- ngx_destroy_pool (cp);
504
+ if (cp != nullptr ) {
505
+ ngx_destroy_pool (cp);
506
+ }
507
+ if (rp != nullptr ) {
508
+ ngx_destroy_pool (rp);
509
+ }
510
+ ngx_destroy_pool (ep);
520
511
}
521
512
522
513
// A finalize handler. Called by NGINX when request is complete (success)
@@ -612,6 +603,11 @@ void ngx_esp_upstream_finalize_request(ngx_http_request_t *r, ngx_int_t rc) {
612
603
613
604
// Schedule the wakeup call with NGINX.
614
605
ngx_post_event (&http_connection->wakeup_event , &ngx_posted_events);
606
+
607
+ // upstream will call output filter chain. Its postpone filter checks
608
+ // content_length with subrequest_output_buffer_size. By clearing it
609
+ // to make sure it passes the postone filter.
610
+ ngx_http_clear_content_length (r);
615
611
}
616
612
617
613
// An input filter initialization handler.
@@ -754,37 +750,39 @@ class ngx_pool_t_deleter {
754
750
// over them (the subrequest code has less control over pools than we have
755
751
// here), a single pool could work as well.
756
752
Status allocate_pools (
757
- ngx_log_t *log ,
758
- std::unique_ptr<ngx_pool_t , ngx_pool_t_deleter> *out_connection_pool,
759
- std::unique_ptr<ngx_pool_t , ngx_pool_t_deleter> *out_request_pool) {
760
- // Only these structures will be allocated from the pool. No need to allocate
761
- // pool bigger than necessary.
762
- const size_t kConnectionPoolSize = sizeof (ngx_pool_t ) +
763
- sizeof (ngx_pool_cleanup_t ) +
764
- sizeof (ngx_esp_http_connection);
765
-
766
- // Create the connection pool.
767
- std::unique_ptr<ngx_pool_t , ngx_pool_t_deleter> connection_pool (
768
- ngx_create_pool (kConnectionPoolSize , log ));
753
+ ngx_log_t *log , std::unique_ptr<ngx_pool_t , ngx_pool_t_deleter> &esp_pool,
754
+ std::unique_ptr<ngx_pool_t , ngx_pool_t_deleter> &connection_pool,
755
+ std::unique_ptr<ngx_pool_t , ngx_pool_t_deleter> &request_pool) {
756
+ // Only esp_http_connection will be allocated from the pool. No need to
757
+ // allocate pool bigger than necessary.
758
+ const size_t kEspPoolSize = sizeof (ngx_pool_t ) + sizeof (ngx_pool_cleanup_t ) +
759
+ sizeof (ngx_esp_http_connection);
760
+ esp_pool.reset (ngx_create_pool (kEspPoolSize , log ));
761
+ if (esp_pool == nullptr ) {
762
+ return Status (NGX_ERROR, " Out of memory" );
763
+ }
764
+
765
+ // Only a clean up is allocated from list pool
766
+ const size_t kConnectionPoolSize =
767
+ sizeof (ngx_pool_t ) + sizeof (ngx_pool_cleanup_t );
768
+ connection_pool.reset (ngx_create_pool (kConnectionPoolSize , log ));
769
769
if (connection_pool == nullptr ) {
770
770
return Status (NGX_ERROR, " Out of memory" );
771
771
}
772
772
773
773
// Allocate the request pool.
774
- std::unique_ptr<ngx_pool_t , ngx_pool_t_deleter> request_pool (
775
- ngx_create_pool (kRequestPoolSize , log ));
774
+ request_pool.reset (ngx_create_pool (kRequestPoolSize , log ));
776
775
if (request_pool == nullptr ) {
777
776
return Status (NGX_ERROR, " Out of memory" );
778
777
}
779
778
779
+ ngx_log_debug1 (NGX_LOG_DEBUG_HTTP, log , 0 , " created HTTP ESP pool: %p" ,
780
+ esp_pool.get ());
780
781
ngx_log_debug1 (NGX_LOG_DEBUG_HTTP, log , 0 , " created HTTP connection pool: %p" ,
781
782
connection_pool.get ());
782
783
ngx_log_debug1 (NGX_LOG_DEBUG_HTTP, log , 0 , " created HTTP request pool: %p" ,
783
784
request_pool.get ());
784
785
785
- *out_connection_pool = std::move (connection_pool);
786
- *out_request_pool = std::move (request_pool);
787
-
788
786
return Status::OK;
789
787
}
790
788
@@ -1104,20 +1102,20 @@ Status ngx_esp_create_http_request(
1104
1102
ngx_log_t *log , HTTPRequest *request,
1105
1103
ngx_esp_http_connection **out_http_connection) {
1106
1104
// Create the connection pool and request pools.
1105
+ std::unique_ptr<ngx_pool_t , ngx_pool_t_deleter> esp_pool;
1107
1106
std::unique_ptr<ngx_pool_t , ngx_pool_t_deleter> connection_pool;
1108
1107
std::unique_ptr<ngx_pool_t , ngx_pool_t_deleter> request_pool;
1109
1108
1110
- Status status = allocate_pools (log , & connection_pool, & request_pool);
1109
+ Status status = allocate_pools (log , esp_pool, connection_pool, request_pool);
1111
1110
if (!status.ok ()) {
1112
1111
return status;
1113
1112
}
1114
1113
1115
1114
// Allocate the HTTP connection state in one go.
1116
1115
// Because we custom-fit the pool size to match this one allocation, the
1117
1116
// alloction will not fail.
1118
- ngx_esp_http_connection *http_connection =
1119
- RegisterPoolCleanup (connection_pool.get (), new (connection_pool.get ())
1120
- ngx_esp_http_connection ());
1117
+ ngx_esp_http_connection *http_connection = RegisterPoolCleanup (
1118
+ esp_pool.get (), new (esp_pool.get ()) ngx_esp_http_connection ());
1121
1119
ngx_log_debug1 (NGX_LOG_DEBUG_HTTP, log , 0 ,
1122
1120
" esp: allocated http_connection %p" , http_connection);
1123
1121
if (http_connection == nullptr ) {
@@ -1160,6 +1158,15 @@ Status ngx_esp_create_http_request(
1160
1158
return status;
1161
1159
}
1162
1160
1161
+ // connection_pool and request_pool can be freed by Nginx.
1162
+ // If the pool is freed, the cleanup function will reset the pointer.
1163
+ http_connection->esp_pool = esp_pool.get ();
1164
+ http_connection->connection_pool_reset .pool = connection_pool.get ();
1165
+ http_connection->request_pool_reset .pool = request_pool.get ();
1166
+ RegisterPoolCleanup (connection_pool.get (),
1167
+ &http_connection->connection_pool_reset );
1168
+ RegisterPoolCleanup (request_pool.get (), &http_connection->request_pool_reset );
1169
+
1163
1170
// Success. Release the pool smart pointers.
1164
1171
//
1165
1172
// The pools are now owned by the connection and request objects
@@ -1170,6 +1177,7 @@ Status ngx_esp_create_http_request(
1170
1177
// connection pool: http_connection->connection.pool
1171
1178
//
1172
1179
// They will be destroyed in wakeup_event_handler.
1180
+ esp_pool.release ();
1173
1181
connection_pool.release ();
1174
1182
request_pool.release ();
1175
1183
0 commit comments