Mercurial > hg > nginx
comparison src/http/modules/ngx_http_fastcgi_module.c @ 5064:10f5831cf56e stable-1.2
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).
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 11 Feb 2013 16:11:14 +0000 |
parents | 05beaa2d87b3 |
children |
comparison
equal
deleted
inserted
replaced
5063:6b5c3eab095c | 5064:10f5831cf56e |
---|---|
1354 | 1354 |
1355 return NGX_AGAIN; | 1355 return NGX_AGAIN; |
1356 } | 1356 } |
1357 | 1357 |
1358 } else { | 1358 } else { |
1359 if (f->padding) { | 1359 f->state = ngx_http_fastcgi_st_padding; |
1360 f->state = ngx_http_fastcgi_st_padding; | |
1361 } else { | |
1362 f->state = ngx_http_fastcgi_st_version; | |
1363 } | |
1364 } | 1360 } |
1365 | 1361 |
1366 continue; | 1362 continue; |
1367 } | 1363 } |
1368 | 1364 |
1595 } | 1591 } |
1596 | 1592 |
1597 f->length -= u->buffer.pos - start; | 1593 f->length -= u->buffer.pos - start; |
1598 | 1594 |
1599 if (f->length == 0) { | 1595 if (f->length == 0) { |
1600 if (f->padding) { | 1596 f->state = ngx_http_fastcgi_st_padding; |
1601 f->state = ngx_http_fastcgi_st_padding; | |
1602 } else { | |
1603 f->state = ngx_http_fastcgi_st_version; | |
1604 } | |
1605 } | 1597 } |
1606 | 1598 |
1607 if (rc == NGX_HTTP_PARSE_HEADER_DONE) { | 1599 if (rc == NGX_HTTP_PARSE_HEADER_DONE) { |
1608 return NGX_OK; | 1600 return NGX_OK; |
1609 } | 1601 } |
1694 if (rc == NGX_ERROR) { | 1686 if (rc == NGX_ERROR) { |
1695 return NGX_ERROR; | 1687 return NGX_ERROR; |
1696 } | 1688 } |
1697 | 1689 |
1698 if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) { | 1690 if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) { |
1699 | 1691 f->state = ngx_http_fastcgi_st_padding; |
1700 if (f->padding) { | |
1701 f->state = ngx_http_fastcgi_st_padding; | |
1702 } else { | |
1703 f->state = ngx_http_fastcgi_st_version; | |
1704 } | |
1705 | 1692 |
1706 if (!flcf->keep_conn) { | 1693 if (!flcf->keep_conn) { |
1707 p->upstream_done = 1; | 1694 p->upstream_done = 1; |
1708 } | 1695 } |
1709 | 1696 |
1713 continue; | 1700 continue; |
1714 } | 1701 } |
1715 | 1702 |
1716 if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) { | 1703 if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) { |
1717 | 1704 |
1718 if (f->padding) { | |
1719 f->state = ngx_http_fastcgi_st_padding; | |
1720 } else { | |
1721 f->state = ngx_http_fastcgi_st_version; | |
1722 } | |
1723 | |
1724 p->upstream_done = 1; | |
1725 | |
1726 if (flcf->keep_conn) { | |
1727 r->upstream->keepalive = 1; | |
1728 } | |
1729 | |
1730 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0, | 1705 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0, |
1731 "http fastcgi sent end request"); | 1706 "http fastcgi sent end request"); |
1732 | 1707 |
1708 if (!flcf->keep_conn) { | |
1709 p->upstream_done = 1; | |
1710 break; | |
1711 } | |
1712 | |
1713 continue; | |
1714 } | |
1715 } | |
1716 | |
1717 | |
1718 if (f->state == ngx_http_fastcgi_st_padding) { | |
1719 | |
1720 if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) { | |
1721 | |
1722 if (f->pos + f->padding < f->last) { | |
1723 p->upstream_done = 1; | |
1724 break; | |
1725 } | |
1726 | |
1727 if (f->pos + f->padding == f->last) { | |
1728 p->upstream_done = 1; | |
1729 r->upstream->keepalive = 1; | |
1730 break; | |
1731 } | |
1732 | |
1733 f->padding -= f->last - f->pos; | |
1734 | |
1733 break; | 1735 break; |
1734 } | 1736 } |
1735 } | |
1736 | |
1737 | |
1738 if (f->state == ngx_http_fastcgi_st_padding) { | |
1739 | 1737 |
1740 if (f->pos + f->padding < f->last) { | 1738 if (f->pos + f->padding < f->last) { |
1741 f->state = ngx_http_fastcgi_st_version; | 1739 f->state = ngx_http_fastcgi_st_version; |
1742 f->pos += f->padding; | 1740 f->pos += f->padding; |
1743 | 1741 |
1786 | 1784 |
1787 ngx_log_error(NGX_LOG_ERR, p->log, 0, | 1785 ngx_log_error(NGX_LOG_ERR, p->log, 0, |
1788 "FastCGI sent in stderr: \"%*s\"", | 1786 "FastCGI sent in stderr: \"%*s\"", |
1789 m + 1 - msg, msg); | 1787 m + 1 - msg, msg); |
1790 | 1788 |
1791 if (f->pos == f->last) { | |
1792 break; | |
1793 } | |
1794 | |
1795 } else { | 1789 } else { |
1796 if (f->padding) { | 1790 f->state = ngx_http_fastcgi_st_padding; |
1797 f->state = ngx_http_fastcgi_st_padding; | |
1798 } else { | |
1799 f->state = ngx_http_fastcgi_st_version; | |
1800 } | |
1801 } | 1791 } |
1802 | 1792 |
1803 continue; | 1793 continue; |
1794 } | |
1795 | |
1796 if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) { | |
1797 | |
1798 if (f->pos + f->length <= f->last) { | |
1799 f->state = ngx_http_fastcgi_st_padding; | |
1800 f->pos += f->length; | |
1801 | |
1802 continue; | |
1803 } | |
1804 | |
1805 f->length -= f->last - f->pos; | |
1806 | |
1807 break; | |
1804 } | 1808 } |
1805 | 1809 |
1806 | 1810 |
1807 /* f->type == NGX_HTTP_FASTCGI_STDOUT */ | 1811 /* f->type == NGX_HTTP_FASTCGI_STDOUT */ |
1808 | 1812 |
1854 /* STUB */ b->num = buf->num; | 1858 /* STUB */ b->num = buf->num; |
1855 | 1859 |
1856 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0, | 1860 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0, |
1857 "input buf #%d %p", b->num, b->pos); | 1861 "input buf #%d %p", b->num, b->pos); |
1858 | 1862 |
1859 if (f->pos + f->length < f->last) { | 1863 if (f->pos + f->length <= f->last) { |
1860 | 1864 f->state = ngx_http_fastcgi_st_padding; |
1861 if (f->padding) { | |
1862 f->state = ngx_http_fastcgi_st_padding; | |
1863 } else { | |
1864 f->state = ngx_http_fastcgi_st_version; | |
1865 } | |
1866 | |
1867 f->pos += f->length; | 1865 f->pos += f->length; |
1868 b->last = f->pos; | 1866 b->last = f->pos; |
1869 | 1867 |
1870 continue; | 1868 continue; |
1871 } | |
1872 | |
1873 if (f->pos + f->length == f->last) { | |
1874 | |
1875 if (f->padding) { | |
1876 f->state = ngx_http_fastcgi_st_padding; | |
1877 } else { | |
1878 f->state = ngx_http_fastcgi_st_version; | |
1879 } | |
1880 | |
1881 b->last = f->last; | |
1882 | |
1883 break; | |
1884 } | 1869 } |
1885 | 1870 |
1886 f->length -= f->last - f->pos; | 1871 f->length -= f->last - f->pos; |
1887 | 1872 |
1888 b->last = f->last; | 1873 b->last = f->last; |