# HG changeset patch # User Igor Sysoev # Date 1125345600 -14400 # Node ID 962c4396064461eeec5befa1a999f35c45d7f014 # Parent ed21d13ec23cdccd67047481e71185bb3a30a72e nginx 0.1.43 *) Feature: the listen(2) backlog in the "listen" directive can be changed using the -HUP signal. *) Feature: the geo2nginx.pl script was added to contrib. *) Change: the FastCGI parameters with the empty values now are passed to a server. *) Bugfix: the segmentation fault occurred or the worker process may got caught in an endless loop if the proxied or FastCGI server sent the "Cache-Control" header line and the "expires" directive was used; in the proxied mode the bug appeared in 0.1.29. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,19 @@ + +Changes with nginx 0.1.43 30 Aug 2005 + + *) Feature: the listen(2) backlog in the "listen" directive can be + changed using the -HUP signal. + + *) Feature: the geo2nginx.pl script was added to contrib. + + *) Change: the FastCGI parameters with the empty values now are passed + to a server. + + *) Bugfix: the segmentation fault occurred or the worker process may + got caught in an endless loop if the proxied or FastCGI server sent + the "Cache-Control" header line and the "expires" directive was + used; in the proxied mode the bug appeared in 0.1.29. + Changes with nginx 0.1.42 23 Aug 2005 diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,3 +1,19 @@ + +Изменения в nginx 0.1.43 30.08.2005 + + *) Добавление: listen(2) backlog в директиве listen можно менять по + сигналу -HUP. + + *) Добавление: скрипт geo2nginx.pl добавлен в contrib. + + *) Изменение: параметры FastCGI, с пустым значениями, теперь передаются + серверу. + + *) Исправление: если в ответе проксированного сервера или FastCGI + сервера была строка "Cache-Control", то при использовании директивы + expires происходил segmentation fault или рабочий процесс мог + зациклится; в режиме прокси ошибка появилась в 0.1.29. + Изменения в nginx 0.1.42 23.08.2005 diff --git a/conf/fastcgi_params b/conf/fastcgi_params new file mode 100644 --- /dev/null +++ b/conf/fastcgi_params @@ -0,0 +1,23 @@ + +fastcgi_param QUERY_STRING $query_string; +fastcgi_param REQUEST_METHOD $request_method; +fastcgi_param CONTENT_TYPE $content_type; +fastcgi_param CONTENT_LENGTH $content_length; + +fastcgi_param SCRIPT_NAME $fastcgi_script_name; +fastcgi_param REQUEST_URI $request_uri; +fastcgi_param DOCUMENT_URI $document_uri; +fastcgi_param DOCUMENT_ROOT $document_root; +fastcgi_param SERVER_PROTOCOL $server_protocol; + +fastcgi_param GATEWAY_INTERFACE CGI/1.1; +fastcgi_param SERVER_SOFTWARE nginx; + +fastcgi_param REMOTE_ADDR $remote_addr; +fastcgi_param REMOTE_PORT $remote_port; +fastcgi_param SERVER_ADDR $server_addr; +fastcgi_param SERVER_PORT $server_port; +fastcgi_param SERVER_NAME $server_name; + +# PHP only, required if PHP was built with --enable-force-cgi-redirect +fastcgi_param REDIRECT_STATUS 200; diff --git a/contrib/README b/contrib/README new file mode 100644 --- /dev/null +++ b/contrib/README @@ -0,0 +1,6 @@ + +geo2nginx.pl by Andrei Nigmatulin + + The perl script to convert CSV geoip database (free download + at http://www.maxmind.com/app/geoip_country) to format, suitable + for use with ngx_http_geo_module. diff --git a/contrib/geo2nginx.pl b/contrib/geo2nginx.pl new file mode 100644 --- /dev/null +++ b/contrib/geo2nginx.pl @@ -0,0 +1,58 @@ +#!/usr/bin/perl -w + +# (c) Andrei Nigmatulin, 2005 +# +# this script provided "as is", without any warranties. use it at your own risk. +# +# special thanx to Andrew Sitnikov for perl port +# +# this script converts CSV geoip database (free download at http://www.maxmind.com/app/geoip_country) +# to format, suitable for use with nginx_http_geo module (http://sysoev.ru/nginx) +# +# for example, line with ip range +# +# "62.16.68.0","62.16.127.255","1041253376","1041268735","RU","Russian Federation" +# +# will be converted to four subnetworks: +# +# 62.16.68.0/22 RU; +# 62.16.72.0/21 RU; +# 62.16.80.0/20 RU; +# 62.16.96.0/19 RU; + + +use warnings; +use strict; + +while( ){ + if (/"[^"]+","[^"]+","([^"]+)","([^"]+)","([^"]+)"/){ + print_subnets($1, $2, $3); + } +} + +sub print_subnets { + my ($a1, $a2, $c) = @_; + my $l; + while ($a1 <= $a2) { + for ($l = 0; ($a1 & (1 << $l)) == 0 && ($a1 + ((1 << ($l + 1)) - 1)) <= $a2; $l++){}; + print long2ip($a1) . "/" . (32 - $l) . " " . $c . ";\n"; + $a1 += (1 << $l); + } +} + +sub long2ip { + my $ip = shift; + + my $str = 0; + + $str = ($ip & 255); + + $ip >>= 8; + $str = ($ip & 255).".$str"; + + $ip >>= 8; + $str = ($ip & 255).".$str"; + + $ip >>= 8; + $str = ($ip & 255).".$str"; +} diff --git a/src/core/nginx.c b/src/core/nginx.c --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -288,9 +288,9 @@ ngx_add_inherited_sockets(ngx_cycle_t *c s = ngx_atoi(v, p - v); if (s == NGX_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, - "invalid socket number \"%s\" in " - NGINX_VAR " environment variable, " - "ignoring the rest of the variable", v); + "invalid socket number \"%s\" in " NGINX_VAR + " environment variable, ignoring the rest" + " of the variable", v); break; } diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,7 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VER "nginx/0.1.42" +#define NGINX_VER "nginx/0.1.43" #define NGINX_VAR "NGINX" #define NGX_NEWPID_EXT ".newbin" diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -123,6 +123,8 @@ ngx_set_inherited_sockets(ngx_cycle_t *c ntohs(sin->sin_port)) - ls[i].addr_text.data; + ls[i].backlog = -1; + #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) ngx_memzero(&af, sizeof(struct accept_filter_arg)); @@ -467,7 +469,8 @@ ngx_connection_error(ngx_connection_t *c return 0; } - if (err == NGX_ECONNRESET + if (err == 0 + || err == NGX_ECONNRESET #if !(NGX_WIN32) || err == NGX_EPIPE #endif diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -45,6 +45,7 @@ typedef struct { unsigned bound:1; /* already bound */ unsigned inherited:1; /* inherited from previous process */ unsigned nonblocking_accept:1; + unsigned change_backlog:1; unsigned nonblocking:1; unsigned shared:1; /* shared between threads or processes */ unsigned addr_ntop:1; diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -339,6 +339,10 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t nls[n].remain = 1; ls[i].remain = 1; + if (ls[n].backlog != nls[i].backlog) { + nls[n].change_backlog = 1; + } + #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) /* @@ -405,12 +409,21 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t failed = 1; } -#if (NGX_HAVE_DEFERRED_ACCEPT) - if (!failed) { ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { + if (ls[i].change_backlog) { + if (listen(ls[i].fd, ls[i].backlog) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno, + "changing the listen() backlog to %d " + "for %V failed, ignored", + &ls[i].addr_text, ls[i].backlog); + } + } + +#if (NGX_HAVE_DEFERRED_ACCEPT) + #ifdef SO_ACCEPTFILTER if (ls[i].delete_deferred) { if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, @@ -476,9 +489,9 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t ls[i].deferred_accept = 1; } #endif +#endif } } -#endif } } diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -144,15 +144,6 @@ static ngx_http_fastcgi_request_start_t }; -#if 0 -static ngx_str_t ngx_http_fastcgi_methods[] = { - ngx_string("GET"), - ngx_string("HEAD"), - ngx_string("POST") -}; -#endif - - static ngx_str_t ngx_http_fastcgi_script_name = ngx_string("fastcgi_script_name"); @@ -428,9 +419,7 @@ ngx_http_fastcgi_create_request(ngx_http } le.ip += sizeof(uintptr_t); - if (val_len) { - len += 1 + key_len + ((val_len > 127) ? 4 : 1) + val_len; - } + len += 1 + key_len + ((val_len > 127) ? 4 : 1) + val_len; } } @@ -527,22 +516,18 @@ ngx_http_fastcgi_create_request(ngx_http } le.ip += sizeof(uintptr_t); - if (val_len) { - *e.pos++ = (u_char) key_len; + *e.pos++ = (u_char) key_len; - if (val_len > 127) { - *e.pos++ = (u_char) (((val_len >> 24) & 0x7f) | 0x80); - *e.pos++ = (u_char) ((val_len >> 16) & 0xff); - *e.pos++ = (u_char) ((val_len >> 8) & 0xff); - *e.pos++ = (u_char) (val_len & 0xff); + if (val_len > 127) { + *e.pos++ = (u_char) (((val_len >> 24) & 0x7f) | 0x80); + *e.pos++ = (u_char) ((val_len >> 16) & 0xff); + *e.pos++ = (u_char) ((val_len >> 8) & 0xff); + *e.pos++ = (u_char) (val_len & 0xff); - } else { - *e.pos++ = (u_char) val_len; - } + } else { + *e.pos++ = (u_char) val_len; } - e.skip = val_len ? 0 : 1; - while (*(uintptr_t *) e.ip) { code = *(ngx_http_script_code_pt *) e.ip; code((ngx_http_script_engine_t *) &e); diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c --- a/src/http/modules/ngx_http_headers_filter_module.c +++ b/src/http/modules/ngx_http_headers_filter_module.c @@ -73,7 +73,7 @@ ngx_http_headers_filter(ngx_http_request { size_t len; ngx_uint_t i; - ngx_table_elt_t *expires, *cc; + ngx_table_elt_t *expires, *cc, **ccp; ngx_http_headers_conf_t *conf; if (r->headers_out.status != NGX_HTTP_OK || r->main) { @@ -103,9 +103,20 @@ ngx_http_headers_filter(ngx_http_request len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT"); expires->value.len = len - 1; - cc = r->headers_out.cache_control.elts; + ccp = r->headers_out.cache_control.elts; + + if (ccp == NULL) { - if (cc == NULL) { + if (ngx_array_init(&r->headers_out.cache_control, r->pool, + 1, sizeof(ngx_table_elt_t *)) != NGX_OK) + { + return NGX_ERROR; + } + + ccp = ngx_array_push(&r->headers_out.cache_control); + if (ccp == NULL) { + return NGX_ERROR; + } cc = ngx_list_push(&r->headers_out.headers); if (cc == NULL) { @@ -116,10 +127,14 @@ ngx_http_headers_filter(ngx_http_request cc->key.len = sizeof("Cache-Control") - 1; cc->key.data = (u_char *) "Cache-Control"; + *ccp = cc; + } else { for (i = 1; i < r->headers_out.cache_control.nelts; i++) { - cc[i].hash = 0; + ccp[i]->hash = 0; } + + cc = ccp[0]; } if (conf->expires == NGX_HTTP_EXPIRES_EPOCH) { diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -637,8 +637,24 @@ ngx_http_process_request_line(ngx_event_ "http exten: \"%V\"", &r->exten); if (r->http_version < NGX_HTTP_VERSION_10) { + + if (rev->timer_set) { + ngx_del_timer(rev); + } + +#if (NGX_STAT_STUB) + ngx_atomic_dec(ngx_stat_reading); + r->stat_reading = 0; + ngx_atomic_inc(ngx_stat_writing); + r->stat_writing = 1; +#endif + + rev->handler = ngx_http_request_handler; + c->write->handler = ngx_http_request_handler; r->read_event_handler = ngx_http_block_read; + ngx_http_handler(r); + return; } @@ -868,6 +884,7 @@ ngx_http_process_request_headers(ngx_eve r->read_event_handler = ngx_http_block_read; ngx_http_handler(r); + return; } @@ -1783,6 +1800,8 @@ ngx_http_discard_body(ngx_http_request_t return NGX_OK; } + r->discard_body = 1; + size = r->header_in->last - r->header_in->pos; if (size) { diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -362,6 +362,7 @@ struct ngx_http_request_s { unsigned header_only:1; unsigned keepalive:1; unsigned lingering_close:1; + unsigned discard_body:1; unsigned internal:1; unsigned done:1; unsigned utf8:1; diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -31,7 +31,7 @@ ngx_http_read_client_request_body(ngx_ht ngx_http_request_body_t *rb; ngx_http_core_loc_conf_t *clcf; - if (r->request_body) { + if (r->request_body || r->discard_body) { post_handler(r); return NGX_OK; } diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -241,7 +241,9 @@ ngx_http_upstream_init(ngx_http_request_ u = r->upstream; - u->request_bufs = r->request_body->bufs; + if (r->request_body) { + u->request_bufs = r->request_body->bufs; + } if (u->conf->method == NGX_CONF_UNSET_UINT) { u->method = r->method; @@ -250,7 +252,7 @@ ngx_http_upstream_init(ngx_http_request_ u->method = u->conf->method; } - if (u->create_request(r) == NGX_ERROR) { + if (u->create_request(r) != NGX_OK) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } @@ -615,9 +617,8 @@ ngx_http_upstream_send_request(ngx_http_ && !u->request_sent && c->write->pending_eof) { - ngx_log_error(NGX_LOG_ERR, c->log, c->write->kq_errno, - "connect() failed"); - + (void) ngx_connection_error(c, c->write->kq_errno, + "kevent() reported that connect() failed"); ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); return; } @@ -716,12 +717,6 @@ ngx_http_upstream_send_request_handler(n return; } - if (r->connection->write->eof && (!u->cachable || !u->request_sent)) { - ngx_http_upstream_finalize_request(r, u, - NGX_HTTP_INTERNAL_SERVER_ERROR); - return; - } - ngx_http_upstream_send_request(r, u); } @@ -1788,6 +1783,7 @@ static u_char * ngx_http_upstream_log_error(ngx_http_request_t *r, u_char *buf, size_t len) { u_char *p; + ngx_str_t line; uintptr_t escape; ngx_http_upstream_t *u; ngx_peer_connection_t *peer; @@ -1824,33 +1820,35 @@ ngx_http_upstream_log_error(ngx_http_req buf += r->uri.len - u->conf->location->len + escape; len -= r->uri.len - u->conf->location->len + escape; - if (r->args.len) { - p = ngx_snprintf(buf, len, "?%V", &r->args); - len -= p - buf; - buf = p; + } else { + p = ngx_palloc(r->pool, + r->uri.len - u->conf->location->len + escape); + if (p == NULL) { + return buf; } - return ngx_http_log_error_info(r, buf, len); + ngx_escape_uri(p, r->uri.data + u->conf->location->len, + r->uri.len - u->conf->location->len, NGX_ESCAPE_URI); + + line.len = len; + line.data = p; + + return ngx_snprintf(buf, len, "%V", &line); } - p = ngx_palloc(r->pool, r->uri.len - u->conf->location->len + escape); - if (p == NULL) { - return buf; + } else { + line.len = r->uri.len - u->conf->location->len; + if (line.len > len) { + line.len = len; } - ngx_escape_uri(p, r->uri.data + u->conf->location->len, - r->uri.len - u->conf->location->len, NGX_ESCAPE_URI); - - p = ngx_cpymem(buf, p, r->uri.len - u->conf->location->len + escape); + line.data = r->uri.data + u->conf->location->len; + p = ngx_snprintf(buf, len, "%V", &line); - } else { - p = ngx_cpymem(buf, r->uri.data + u->conf->location->len, - r->uri.len - u->conf->location->len); + len -= p - buf; + buf = p; } - len -= p - buf; - buf = p; - if (r->args.len) { p = ngx_snprintf(buf, len, "?%V", &r->args); len -= p - buf; diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c --- a/src/os/unix/ngx_freebsd_sendfile_chain.c +++ b/src/os/unix/ngx_freebsd_sendfile_chain.c @@ -57,9 +57,8 @@ ngx_freebsd_sendfile_chain(ngx_connectio #if (NGX_HAVE_KQUEUE) if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) { - ngx_log_error(NGX_LOG_INFO, c->log, wev->kq_errno, - "kevent() reported about an closed connection"); - + (void) ngx_connection_error(c, wev->kq_errno, + "kevent() reported about an closed connection"); wev->error = 1; return NGX_CHAIN_ERROR; } @@ -228,8 +227,8 @@ ngx_freebsd_sendfile_chain(ngx_connectio if (err != NGX_EINTR) { wev->error = 1; - ngx_connection_error(c, err, - ngx_tcp_nopush_n " failed"); + (void) ngx_connection_error(c, err, + ngx_tcp_nopush_n " failed"); return NGX_CHAIN_ERROR; } @@ -276,7 +275,7 @@ ngx_freebsd_sendfile_chain(ngx_connectio } else { wev->error = 1; - ngx_connection_error(c, err, "sendfile() failed"); + (void) ngx_connection_error(c, err, "sendfile() failed"); return NGX_CHAIN_ERROR; } } diff --git a/src/os/unix/ngx_recv.c b/src/os/unix/ngx_recv.c --- a/src/os/unix/ngx_recv.c +++ b/src/os/unix/ngx_recv.c @@ -29,20 +29,12 @@ ssize_t ngx_unix_recv(ngx_connection_t * rev->ready = 0; rev->eof = 1; - ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno, - "kevent() reported about an closed connection"); - if (rev->kq_errno) { rev->error = 1; ngx_set_socket_errno(rev->kq_errno); - if (rev->kq_errno == NGX_ECONNRESET - && c->log_error == NGX_ERROR_IGNORE_ECONNRESET) - { - return 0; - } - - return NGX_ERROR; + return ngx_connection_error(c, rev->kq_errno, + "kevent() reported about an closed connection"); } return 0; diff --git a/src/os/unix/ngx_send.c b/src/os/unix/ngx_send.c --- a/src/os/unix/ngx_send.c +++ b/src/os/unix/ngx_send.c @@ -20,9 +20,8 @@ ssize_t ngx_unix_send(ngx_connection_t * #if (NGX_HAVE_KQUEUE) if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) { - ngx_log_error(NGX_LOG_INFO, c->log, wev->kq_errno, - "kevent() reported about an closed connection"); - + (void) ngx_connection_error(c, wev->kq_errno, + "kevent() reported about an closed connection"); wev->error = 1; return NGX_ERROR; } @@ -63,7 +62,7 @@ ssize_t ngx_unix_send(ngx_connection_t * } else { wev->error = 1; - ngx_connection_error(c, err, "send() failed"); + (void) ngx_connection_error(c, err, "send() failed"); return NGX_ERROR; } } diff --git a/src/os/unix/ngx_writev_chain.c b/src/os/unix/ngx_writev_chain.c --- a/src/os/unix/ngx_writev_chain.c +++ b/src/os/unix/ngx_writev_chain.c @@ -34,9 +34,8 @@ ngx_writev_chain(ngx_connection_t *c, ng #if (NGX_HAVE_KQUEUE) if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) { - ngx_log_error(NGX_LOG_INFO, c->log, wev->kq_errno, - "kevent() reported about an closed connection"); - + (void) ngx_connection_error(c, wev->kq_errno, + "kevent() reported about an closed connection"); wev->error = 1; return NGX_CHAIN_ERROR; } @@ -117,7 +116,7 @@ ngx_writev_chain(ngx_connection_t *c, ng } else { wev->error = 1; - ngx_connection_error(c, err, "writev() failed"); + (void) ngx_connection_error(c, err, "writev() failed"); return NGX_CHAIN_ERROR; } }