diff options
author | Maxim Dounin <mdounin@mdounin.ru> | 2013-02-11 16:11:14 +0000 |
---|---|---|
committer | Maxim Dounin <mdounin@mdounin.ru> | 2013-02-11 16:11:14 +0000 |
commit | 7eafb7761e3220b4e882e6c474fc7bebd3190dc7 (patch) | |
tree | 9d673c60d210ecd95d1b3d34bbbc321e54188602 | |
parent | 61312182f5b08cafc33bd4ebe15d3c2defb4a998 (diff) | |
download | nginx-7eafb7761e3220b4e882e6c474fc7bebd3190dc7.tar.gz |
Merge of r5027, r5028, r5029: fastcgi_keep_conn fixes.
*) FastCGI: fixed wrong connection close with fastcgi_keep_conn.
With fastcgi_keep_conn it was possible that connection was closed after
FCGI_STDERR record with zero padding and without any further data read
yet. This happended as f->state was set to ngx_http_fastcgi_st_padding
and then "break" happened, resulting in p->length being set to
f->padding, i.e. 0 (which in turn resulted in connection close).
Fix is to make sure we continue the loop after f->state is set.
*) FastCGI: unconditional state transitions. Checks for f->padding
before state transitions make code hard to follow, remove them and
make sure we always do another loop iteration after f->state is
set to ngx_http_fastcgi_st_padding.
*) FastCGI: proper handling of split fastcgi end request. If fastcgi
end request record was split between several network packets, with
fastcgi_keep_conn it was possible that connection was saved in
incorrect state (e.g. with padding bytes not yet read).
-rw-r--r-- | src/http/modules/ngx_http_fastcgi_module.c | 101 |
1 files changed, 43 insertions, 58 deletions
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index f1917e25d..42eb86e49 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -1356,11 +1356,7 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) } } else { - if (f->padding) { - f->state = ngx_http_fastcgi_st_padding; - } else { - f->state = ngx_http_fastcgi_st_version; - } + f->state = ngx_http_fastcgi_st_padding; } continue; @@ -1597,11 +1593,7 @@ ngx_http_fastcgi_process_header(ngx_http_request_t *r) f->length -= u->buffer.pos - start; if (f->length == 0) { - if (f->padding) { - f->state = ngx_http_fastcgi_st_padding; - } else { - f->state = ngx_http_fastcgi_st_version; - } + f->state = ngx_http_fastcgi_st_padding; } if (rc == NGX_HTTP_PARSE_HEADER_DONE) { @@ -1696,12 +1688,7 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf) } if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) { - - if (f->padding) { - f->state = ngx_http_fastcgi_st_padding; - } else { - f->state = ngx_http_fastcgi_st_version; - } + f->state = ngx_http_fastcgi_st_padding; if (!flcf->keep_conn) { p->upstream_done = 1; @@ -1715,27 +1702,38 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf) if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) { - if (f->padding) { - f->state = ngx_http_fastcgi_st_padding; - } else { - f->state = ngx_http_fastcgi_st_version; + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0, + "http fastcgi sent end request"); + + if (!flcf->keep_conn) { + p->upstream_done = 1; + break; } - p->upstream_done = 1; + continue; + } + } + + + if (f->state == ngx_http_fastcgi_st_padding) { + + if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) { - if (flcf->keep_conn) { + if (f->pos + f->padding < f->last) { + p->upstream_done = 1; + break; + } + + if (f->pos + f->padding == f->last) { + p->upstream_done = 1; r->upstream->keepalive = 1; + break; } - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0, - "http fastcgi sent end request"); + f->padding -= f->last - f->pos; break; } - } - - - if (f->state == ngx_http_fastcgi_st_padding) { if (f->pos + f->padding < f->last) { f->state = ngx_http_fastcgi_st_version; @@ -1788,21 +1786,27 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf) "FastCGI sent in stderr: \"%*s\"", m + 1 - msg, msg); - if (f->pos == f->last) { - break; - } - } else { - if (f->padding) { - f->state = ngx_http_fastcgi_st_padding; - } else { - f->state = ngx_http_fastcgi_st_version; - } + f->state = ngx_http_fastcgi_st_padding; } continue; } + if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) { + + if (f->pos + f->length <= f->last) { + f->state = ngx_http_fastcgi_st_padding; + f->pos += f->length; + + continue; + } + + f->length -= f->last - f->pos; + + break; + } + /* f->type == NGX_HTTP_FASTCGI_STDOUT */ @@ -1856,33 +1860,14 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf) ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0, "input buf #%d %p", b->num, b->pos); - if (f->pos + f->length < f->last) { - - if (f->padding) { - f->state = ngx_http_fastcgi_st_padding; - } else { - f->state = ngx_http_fastcgi_st_version; - } - + if (f->pos + f->length <= f->last) { + f->state = ngx_http_fastcgi_st_padding; f->pos += f->length; b->last = f->pos; continue; } - if (f->pos + f->length == f->last) { - - if (f->padding) { - f->state = ngx_http_fastcgi_st_padding; - } else { - f->state = ngx_http_fastcgi_st_version; - } - - b->last = f->last; - - break; - } - f->length -= f->last - f->pos; b->last = f->last; |