comparison src/http/ngx_http_upstream_round_robin.c @ 4167:e917fc5eceb7 stable-1.0

Merging r4011, r4012, r4136: Proxy related fixes: *) Fixing cpu hog with all upstream servers marked "down". The following configuration causes nginx to hog cpu due to infinite loop in ngx_http_upstream_get_peer(): upstream backend { server 127.0.0.1:8080 down; server 127.0.0.1:8080 down; } server { ... location / { proxy_pass http://backend; } } Make sure we don't loop infinitely in ngx_http_upstream_get_peer() but stop after resetting peer weights once. Return 0 if we are stuck. This is guaranteed to work as peer 0 always exists, and eventually ngx_http_upstream_get_round_robin_peer() will do the right thing falling back to backup servers or returning NGX_BUSY. *) Upstream: properly allocate memory for tried flags. Previous allocation only took into account number of non-backup servers, and this caused memory corruption with many backup servers. See report here: http://mailman.nginx.org/pipermail/nginx/2011-May/026531.html *) Fix of cpu hog in event pipe. If client closed connection in ngx_event_pipe_write_to_downstream(), buffers in the "out" chain were lost. This caused cpu hog if all available buffers were in the "out" chain. Fix is to call ngx_chain_update_chains() before checking return code of output filter to avoid loosing buffers in the "out" chain. Note that this situation (all available buffers in the "out" chain) isn't normal, it should be prevented by busy buffers limit. Though right now it may happen with complex protocols like fastcgi. This should be addressed separately.
author Igor Sysoev <igor@sysoev.ru>
date Fri, 30 Sep 2011 14:30:01 +0000
parents f87edc142316
children 4919fb357a5d
comparison
equal deleted inserted replaced
4166:525a34d74a0a 4167:e917fc5eceb7
226 } 226 }
227 227
228 rrp->peers = us->peer.data; 228 rrp->peers = us->peer.data;
229 rrp->current = 0; 229 rrp->current = 0;
230 230
231 if (rrp->peers->number <= 8 * sizeof(uintptr_t)) { 231 n = rrp->peers->number;
232
233 if (rrp->peers->next && rrp->peers->next->number > n) {
234 n = rrp->peers->next->number;
235 }
236
237 if (n <= 8 * sizeof(uintptr_t)) {
232 rrp->tried = &rrp->data; 238 rrp->tried = &rrp->data;
233 rrp->data = 0; 239 rrp->data = 0;
234 240
235 } else { 241 } else {
236 n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1)) 242 n = (n + (8 * sizeof(uintptr_t) - 1)) / (8 * sizeof(uintptr_t));
237 / (8 * sizeof(uintptr_t));
238 243
239 rrp->tried = ngx_pcalloc(r->pool, n * sizeof(uintptr_t)); 244 rrp->tried = ngx_pcalloc(r->pool, n * sizeof(uintptr_t));
240 if (rrp->tried == NULL) { 245 if (rrp->tried == NULL) {
241 return NGX_ERROR; 246 return NGX_ERROR;
242 } 247 }
583 588
584 589
585 static ngx_uint_t 590 static ngx_uint_t
586 ngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers) 591 ngx_http_upstream_get_peer(ngx_http_upstream_rr_peers_t *peers)
587 { 592 {
588 ngx_uint_t i, n; 593 ngx_uint_t i, n, reset = 0;
589 ngx_http_upstream_rr_peer_t *peer; 594 ngx_http_upstream_rr_peer_t *peer;
590 595
591 peer = &peers->peer[0]; 596 peer = &peers->peer[0];
592 597
593 for ( ;; ) { 598 for ( ;; ) {
622 } 627 }
623 628
624 return n; 629 return n;
625 } 630 }
626 631
632 if (reset++) {
633 return 0;
634 }
635
627 for (i = 0; i < peers->number; i++) { 636 for (i = 0; i < peers->number; i++) {
628 peer[i].current_weight = peer[i].weight; 637 peer[i].current_weight = peer[i].weight;
629 } 638 }
630 } 639 }
631 } 640 }