# HG changeset patch # User Igor Sysoev # Date 1169154000 -10800 # Node ID c5c2b2883984319372d9affe7a5e3dc7c9d5ad6d # Parent 1779577cb845d6106db66b9f8abaa1c541767be3 nginx 0.5.8 *) Bugfix: a segmentation fault might occur if "client_body_in_file_only on" was used and a request body was small. *) Bugfix: a segmentation fault occurred if "client_body_in_file_only on" and "proxy_pass_request_body off" or "fastcgi_pass_request_body off" directives were used, and nginx switched to a next upstream. *) Bugfix: if the "proxy_buffering off" directive was used and a client connection was non-active, then the connection was closed after send timeout; bug appeared in 0.4.7. *) Bugfix: if the "epoll" method was used and a client closed a connection prematurely, then nginx closed the connection after a send timeout only. *) Bugfix: the "[alert] zero size buf" error when FastCGI server was used. *) Bugfixes in the "limit_zone" directive. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,28 @@ +Changes with nginx 0.5.8 19 Jan 2007 + + *) Bugfix: a segmentation fault might occur if + "client_body_in_file_only on" was used and a request body was small. + + *) Bugfix: a segmentation fault occurred if + "client_body_in_file_only on" and "proxy_pass_request_body off" or + "fastcgi_pass_request_body off" directives were used, and nginx + switched to a next upstream. + + *) Bugfix: if the "proxy_buffering off" directive was used and a client + connection was non-active, then the connection was closed after send + timeout; bug appeared in 0.4.7. + + *) Bugfix: if the "epoll" method was used and a client closed a + connection prematurely, then nginx closed the connection after a + send timeout only. + + *) Bugfix: the "[alert] zero size buf" error when FastCGI server was + used. + + *) Bugfixes in the "limit_zone" directive. + + Changes with nginx 0.5.7 15 Jan 2007 *) Feature: the ssl_session_cache storage optimization. @@ -79,7 +103,7 @@ Changes with nginx 0.5.3 *) Feature: the $r->variable method supports variables that do not exist in nginx configuration. - *) Bugfix: the $r->has_request_body method did work. + *) Bugfix: the $r->has_request_body method did not work. Changes with nginx 0.5.2 11 Dec 2006 @@ -463,8 +487,8 @@ Changes with nginx 0.3.55 returns all "Cookie" header lines. *) Bugfix: a segmentation fault occurred if - "client_body_in_file_only on" was used and nginx was switches to a - next upstream. + "client_body_in_file_only on" was used and nginx switched to a next + upstream. *) Bugfix: on some condition while reconfiguration character codes inside the "charset_map" may be treated invalid; bug appeared in diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,29 @@ +Изменения в nginx 0.5.8 19.01.2007 + + *) Исправление: если использовалась директива + "client_body_in_file_only on" и тело запроса было небольшое, то мог + произойти segmentation fault. + + *) Исправление: происходил segmentation fault, если использовались + директивы "client_body_in_file_only on" и + "proxy_pass_request_body off" или "fastcgi_pass_request_body off", и + делался переход к следующему бэкенду. + + *) Исправление: если при использовании директивы "proxy_buffering off" + соединение с клиентом было неактивно, то оно закрывалось по таймуту, + заданному директивой send_timeout; ошибка появилась в 0.4.7. + + *) Исправление: если при использовании метода epoll клиент закрывал + преждевременно соединение со своей стороны, то nginx закрывал это + соединение только по истечении таймаута на передачу. + + *) Исправление: ошибки "[alert] zero size buf" при работе с + FastCGI-сервером. + + *) Исправление ошибок в директиве limit_zone. + + Изменения в nginx 0.5.7 15.01.2007 *) Добавление: оптимизация использования памяти в ssl_session_cache. @@ -13,7 +38,7 @@ add_after_body происходил segmentation fault, если в заголовке ответа нет строки "Content-Type". - *) Исправление: библиотека OpenSSL всегда собирался с поддержкой + *) Исправление: библиотека OpenSSL всегда собиралась с поддержкой потоков. Спасибо Дену Иванову. diff --git a/conf/nginx.conf b/conf/nginx.conf --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -29,7 +29,6 @@ http { #keepalive_timeout 0; keepalive_timeout 65; - tcp_nodelay on; #gzip on; 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_VERSION "0.5.7" +#define NGINX_VERSION "0.5.8" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c --- a/src/core/ngx_conf_file.c +++ b/src/core/ngx_conf_file.c @@ -76,7 +76,7 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t /* open configuration file */ - fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN); + fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, ngx_open_file_n " \"%s\" failed", 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 @@ -312,7 +312,8 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) } file[i].fd = ngx_open_file(file[i].name.data, NGX_FILE_RDWR, - NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND); + NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND, + NGX_FILE_DEFAULT_ACCESS); ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0, "log: %p %d \"%s\"", @@ -849,7 +850,8 @@ ngx_create_pidfile(ngx_str_t *name, ngx_ trunc = ngx_test_config ? 0 : NGX_FILE_TRUNCATE; file.fd = ngx_open_file(file.name.data, NGX_FILE_RDWR, - NGX_FILE_CREATE_OR_OPEN|trunc); + NGX_FILE_CREATE_OR_OPEN|trunc, + NGX_FILE_DEFAULT_ACCESS); if (file.fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, @@ -959,7 +961,8 @@ ngx_reopen_files(ngx_cycle_t *cycle, ngx } fd = ngx_open_file(file[i].name.data, NGX_FILE_RDWR, - NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND); + NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND, + NGX_FILE_DEFAULT_ACCESS); ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reopen file \"%s\", old:%d new:%d", diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c --- a/src/core/ngx_file.c +++ b/src/core/ngx_file.c @@ -19,7 +19,7 @@ ngx_write_chain_to_temp_file(ngx_temp_fi if (tf->file.fd == NGX_INVALID_FILE) { rc = ngx_create_temp_file(&tf->file, tf->path, tf->pool, - tf->persistent, tf->mode); + tf->persistent, tf->access); if (rc == NGX_ERROR || rc == NGX_AGAIN) { return rc; @@ -37,7 +37,7 @@ ngx_write_chain_to_temp_file(ngx_temp_fi ngx_int_t ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, ngx_pool_t *pool, - ngx_uint_t persistent, ngx_uint_t mode) + ngx_uint_t persistent, ngx_uint_t access) { ngx_err_t err; ngx_atomic_uint_t n; @@ -72,7 +72,7 @@ ngx_create_temp_file(ngx_file_t *file, n return NGX_ERROR; } - file->fd = ngx_open_tempfile(file->name.data, persistent, mode); + file->fd = ngx_open_tempfile(file->name.data, persistent, access); ngx_log_debug1(NGX_LOG_DEBUG_CORE, file->log, 0, "temp fd:%d", file->fd); @@ -445,8 +445,8 @@ ngx_walk_tree(ngx_tree_ctx_t *ctx, ngx_s prev = ctx->data; - if (ctx->size) { - data = ngx_alloc(ctx->size, ctx->log); + if (ctx->alloc) { + data = ngx_alloc(ctx->alloc, ctx->log); if (data == NULL) { goto failed; } @@ -529,6 +529,10 @@ ngx_walk_tree(ngx_tree_ctx_t *ctx, ngx_s ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0, "tree file \"%s\"", file.data); + ctx->size = ngx_de_size(&dir); + ctx->access = ngx_de_access(&dir); + ctx->mtime = ngx_de_mtime(&dir); + if (ctx->file_handler(ctx, &file) == NGX_ABORT) { goto failed; } @@ -538,6 +542,9 @@ ngx_walk_tree(ngx_tree_ctx_t *ctx, ngx_s ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0, "tree enter dir \"%s\"", file.data); + ctx->access = ngx_de_access(&dir); + ctx->mtime = ngx_de_mtime(&dir); + if (ctx->pre_tree_handler(ctx, &file) == NGX_ABORT) { goto failed; } @@ -546,6 +553,9 @@ ngx_walk_tree(ngx_tree_ctx_t *ctx, ngx_s goto failed; } + ctx->access = ngx_de_access(&dir); + ctx->mtime = ngx_de_mtime(&dir); + if (ctx->post_tree_handler(ctx, &file) == NGX_ABORT) { goto failed; } @@ -571,7 +581,7 @@ done: ngx_free(buf.data); } - if (ctx->data) { + if (ctx->alloc) { ngx_free(ctx->data); ctx->data = prev; } diff --git a/src/core/ngx_file.h b/src/core/ngx_file.h --- a/src/core/ngx_file.h +++ b/src/core/ngx_file.h @@ -49,7 +49,7 @@ typedef struct { ngx_pool_t *pool; char *warn; - ngx_uint_t mode; + ngx_uint_t access; unsigned log_level:8; unsigned persistent:1; @@ -58,25 +58,30 @@ typedef struct { typedef struct ngx_tree_ctx_s ngx_tree_ctx_t; -typedef ngx_int_t (*ngx_tree_init_handler_pt) (ngx_tree_ctx_t *ctx, - ngx_tree_ctx_t *prev); +typedef ngx_int_t (*ngx_tree_init_handler_pt) (void *ctx, void *prev); typedef ngx_int_t (*ngx_tree_handler_pt) (ngx_tree_ctx_t *ctx, ngx_str_t *name); struct ngx_tree_ctx_s { + off_t size; + ngx_uint_t access; + time_t mtime; + ngx_tree_init_handler_pt init_handler; ngx_tree_handler_pt file_handler; ngx_tree_handler_pt pre_tree_handler; ngx_tree_handler_pt post_tree_handler; ngx_tree_handler_pt spec_handler; + void *data; - size_t size; + size_t alloc; + ngx_log_t *log; }; ssize_t ngx_write_chain_to_temp_file(ngx_temp_file_t *tf, ngx_chain_t *chain); ngx_int_t ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, - ngx_pool_t *pool, ngx_uint_t persistent,ngx_uint_t mode); + ngx_pool_t *pool, ngx_uint_t persistent,ngx_uint_t access); void ngx_create_hashed_filename(ngx_file_t *file, ngx_path_t *path); ngx_int_t ngx_create_path(ngx_file_t *file, ngx_path_t *path); ngx_err_t ngx_create_full_path(u_char *dir, ngx_uint_t access); diff --git a/src/core/ngx_log.c b/src/core/ngx_log.c --- a/src/core/ngx_log.c +++ b/src/core/ngx_log.c @@ -209,7 +209,7 @@ ngx_log_init(void) ngx_stderr_fileno = GetStdHandle(STD_ERROR_HANDLE); ngx_stderr.fd = ngx_open_file(NGX_ERROR_LOG_PATH, NGX_FILE_RDWR, - NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND); + NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND, 0); if (ngx_stderr.fd == NGX_INVALID_FILE) { ngx_message_box("nginx", MB_OK, ngx_errno, @@ -279,7 +279,7 @@ ngx_set_error_log_levels(ngx_conf_t *cf, if (log->log_level != 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid log level \"%s\"", + "duplicate log level \"%s\"", value[i].data); return NGX_CONF_ERROR; } diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -1620,7 +1620,7 @@ ngx_ssl_session_rbtree_insert_value(ngx_ } else if (node->key > temp->key) { - if (temp->right == sentinel) { + if (temp->right == sentinel) { temp->right = node; break; } @@ -1642,9 +1642,9 @@ ngx_ssl_session_rbtree_insert_value(ngx_ } temp = temp->left; - + } else { - + if (temp->right == sentinel) { temp->right = node; break; @@ -1659,7 +1659,7 @@ ngx_ssl_session_rbtree_insert_value(ngx_ node->left = sentinel; node->right = sentinel; ngx_rbt_red(node); -} +} void diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c --- a/src/event/ngx_event_pipe.c +++ b/src/event/ngx_event_pipe.c @@ -420,7 +420,7 @@ static ngx_int_t ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p) { size_t bsize; - ngx_uint_t flush; + ngx_uint_t flush, prev_last_shadow; ngx_chain_t *out, **ll, *cl; ngx_connection_t *downstream; @@ -511,13 +511,13 @@ ngx_event_pipe_write_to_downstream(ngx_e out = NULL; ll = NULL; flush = 0; + prev_last_shadow = 1; for ( ;; ) { if (p->out) { cl = p->out; if (cl->buf->recycled - && cl->buf->last_shadow && bsize + cl->buf->last - cl->buf->pos > p->busy_size) { flush = 1; @@ -541,10 +541,24 @@ ngx_event_pipe_write_to_downstream(ngx_e && cl->buf->last_shadow && bsize + cl->buf->last - cl->buf->pos > p->busy_size) { + if (!prev_last_shadow) { + p->in = p->in->next; + + cl->next = NULL; + + if (out) { + *ll = cl; + } else { + out = cl; + } + } + flush = 1; break; } + prev_last_shadow = cl->buf->last_shadow; + p->in = p->in->next; } else { diff --git a/src/http/modules/ngx_http_auth_basic_module.c b/src/http/modules/ngx_http_auth_basic_module.c --- a/src/http/modules/ngx_http_auth_basic_module.c +++ b/src/http/modules/ngx_http_auth_basic_module.c @@ -133,7 +133,7 @@ ngx_http_auth_basic_handler(ngx_http_req return NGX_HTTP_INTERNAL_SERVER_ERROR; } - fd = ngx_open_file(alcf->user_file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN); + fd = ngx_open_file(alcf->user_file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c --- a/src/http/modules/ngx_http_dav_module.c +++ b/src/http/modules/ngx_http_dav_module.c @@ -19,8 +19,7 @@ typedef struct { static ngx_int_t ngx_http_dav_handler(ngx_http_request_t *r); -static ngx_int_t ngx_http_dav_no_init(ngx_tree_ctx_t *ctx, - ngx_tree_ctx_t *prev); +static ngx_int_t ngx_http_dav_no_init(void *ctx, void *prev); static ngx_int_t ngx_http_dav_noop(ngx_tree_ctx_t *ctx, ngx_str_t *path); static ngx_int_t ngx_http_dav_delete_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path); static ngx_int_t ngx_http_dav_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path); @@ -131,7 +130,7 @@ ngx_http_dav_handler(ngx_http_request_t case NGX_HTTP_PUT: if (r->uri.data[r->uri.len - 1] == '/') { - return NGX_DECLINED; + return NGX_HTTP_BAD_REQUEST; } r->request_body_in_file_only = 1; @@ -190,7 +189,7 @@ ngx_http_dav_handler(ngx_http_request_t tree.post_tree_handler = ngx_http_dav_delete_dir; tree.spec_handler = ngx_http_dav_delete_file; tree.data = NULL; - tree.size = 0; + tree.alloc = 0; tree.log = r->connection->log; if (ngx_walk_tree(&tree, &path) == NGX_OK) { @@ -270,7 +269,7 @@ ngx_http_dav_handler(ngx_http_request_t static ngx_int_t -ngx_http_dav_no_init(ngx_tree_ctx_t *ctx, ngx_tree_ctx_t *prev) +ngx_http_dav_no_init(void *ctx, void *prev) { return NGX_OK; } diff --git a/src/http/modules/ngx_http_empty_gif_module.c b/src/http/modules/ngx_http_empty_gif_module.c --- a/src/http/modules/ngx_http_empty_gif_module.c +++ b/src/http/modules/ngx_http_empty_gif_module.c @@ -158,7 +158,7 @@ ngx_http_empty_gif_handler(ngx_http_requ return rc; } - return ngx_http_output_filter(r, &out);; + return ngx_http_output_filter(r, &out); } 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 @@ -1308,11 +1308,8 @@ ngx_http_fastcgi_input_filter(ngx_event_ /* STUB */ b->num = buf->num; - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "input buf #%d", b->num); - ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0, - "input buf %p %z", b->pos, b->last - b->pos); - + "input buf #%d %p", b->num, b->pos); if (f->pos + f->length < f->last) { @@ -1354,7 +1351,7 @@ ngx_http_fastcgi_input_filter(ngx_event_ b->last_shadow = 1; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0, - "input buf last %p %z", b->pos, b->last - b->pos); + "input buf %p %z", b->pos, b->last - b->pos); return NGX_OK; } diff --git a/src/http/modules/ngx_http_flv_module.c b/src/http/modules/ngx_http_flv_module.c --- a/src/http/modules/ngx_http_flv_module.c +++ b/src/http/modules/ngx_http_flv_module.c @@ -109,7 +109,7 @@ ngx_http_flv_handler(ngx_http_request_t return NGX_HTTP_INTERNAL_SERVER_ERROR; } - fd = ngx_open_file(path.data, NGX_FILE_RDONLY, NGX_FILE_OPEN); + fd = ngx_open_file(path.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { err = ngx_errno; diff --git a/src/http/modules/ngx_http_index_module.c b/src/http/modules/ngx_http_index_module.c --- a/src/http/modules/ngx_http_index_module.c +++ b/src/http/modules/ngx_http_index_module.c @@ -245,7 +245,7 @@ ngx_http_index_handler(ngx_http_request_ return NGX_HTTP_INTERNAL_SERVER_ERROR; } - fd = ngx_open_file(ctx->path.data, NGX_FILE_RDONLY, NGX_FILE_OPEN); + fd = ngx_open_file(ctx->path.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == (ngx_fd_t) NGX_AGAIN) { ctx->current = i; diff --git a/src/http/modules/ngx_http_limit_zone_module.c b/src/http/modules/ngx_http_limit_zone_module.c --- a/src/http/modules/ngx_http_limit_zone_module.c +++ b/src/http/modules/ngx_http_limit_zone_module.c @@ -179,7 +179,7 @@ ngx_http_limit_zone_handler(ngx_http_req do { lz = (ngx_http_limit_zone_node_t *) &node->color; - rc = ngx_memn2cmp(lz->data, vv->data, (size_t) lz->len, len); + rc = ngx_memn2cmp(vv->data, lz->data, len, (size_t) lz->len); if (rc == 0) { if ((ngx_uint_t) lz->conn < lzcf->conn) { diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c --- a/src/http/modules/ngx_http_static_module.c +++ b/src/http/modules/ngx_http_static_module.c @@ -126,7 +126,7 @@ ngx_http_static_handler(ngx_http_request return NGX_HTTP_INTERNAL_SERVER_ERROR; } - fd = ngx_open_file(path.data, NGX_FILE_RDONLY, NGX_FILE_OPEN); + fd = ngx_open_file(path.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { err = ngx_errno; diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm --- a/src/http/modules/perl/nginx.pm +++ b/src/http/modules/perl/nginx.pm @@ -47,7 +47,7 @@ our @EXPORT = qw( HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '0.5.7'; +our $VERSION = '0.5.8'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs --- a/src/http/modules/perl/nginx.xs +++ b/src/http/modules/perl/nginx.xs @@ -632,7 +632,7 @@ sendfile(r, filename, offset = -1, bytes XSRETURN_EMPTY; } - fd = ngx_open_file((u_char *) filename, NGX_FILE_RDONLY, NGX_FILE_OPEN); + fd = ngx_open_file((u_char *) filename, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); if (fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c --- a/src/http/ngx_http_header_filter_module.c +++ b/src/http/ngx_http_header_filter_module.c @@ -87,7 +87,7 @@ static ngx_str_t ngx_http_status_lines[] ngx_string("409 Conflict"), ngx_string("410 Gone"), ngx_string("411 Length Required"), - ngx_null_string, /* "412 Precondition Failed" */ + ngx_string("412 Precondition Failed"), ngx_string("413 Request Entity Too Large"), ngx_null_string, /* "414 Request-URI Too Large", but we never send it * because we treat such requests as the HTTP/0.9 diff --git a/src/http/ngx_http_parse_time.c b/src/http/ngx_http_parse_time.c --- a/src/http/ngx_http_parse_time.c +++ b/src/http/ngx_http_parse_time.c @@ -243,8 +243,8 @@ time_t ngx_http_parse_time(u_char *value */ if (--month <= 0) { - month += 12; - year -= 1; + month += 12; + year -= 1; } /* Gauss's formula for Grigorian days from 1 March 1 BC */ @@ -255,7 +255,7 @@ time_t ngx_http_parse_time(u_char *value /* * 719527 days were between March 1, 1 BC and March 1, 1970, - * 31 and 28 days in January and February 1970 + * 31 and 28 days were in January and February 1970 */ - 719527 + 31 + 28) * 86400 + hour * 3600 + min * 60 + sec; 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 @@ -141,6 +141,9 @@ ngx_http_header_t ngx_http_headers_in[] { ngx_string("Destination"), offsetof(ngx_http_headers_in_t, destination), ngx_http_process_header_line }, + { ngx_string("Overwrite"), offsetof(ngx_http_headers_in_t, overwrite), + ngx_http_process_header_line }, + { ngx_string("Date"), offsetof(ngx_http_headers_in_t, date), ngx_http_process_header_line }, #endif @@ -1762,20 +1765,77 @@ ngx_http_writer(ngx_http_request_t *r) static void ngx_http_block_read(ngx_http_request_t *r) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http read blocked"); + int n; + char buf[1]; + ngx_err_t err; + ngx_event_t *rev; + ngx_connection_t *c; + + c = r->connection; + rev = c->read; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http read blocked"); + +#if (NGX_HAVE_KQUEUE) + + if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { + + if (!rev->pending_eof) { + return; + } + + rev->eof = 1; + c->error = 1; + err = rev->kq_errno; + + goto closed; + } + +#endif + + n = recv(c->fd, buf, 1, MSG_PEEK); + + if (n == 0) { + rev->eof = 1; + c->error = 1; + err = 0; + + goto closed; + + } else if (n == -1) { + err = ngx_socket_errno; + + if (err != NGX_EAGAIN) { + rev->eof = 1; + c->error = 1; + + goto closed; + } + } /* aio does not call this handler */ - if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) - && r->connection->read->active) - { - if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0) - == NGX_ERROR) - { + if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && rev->active) { + + if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) { ngx_http_close_request(r, 0); } } + + return; + +closed: + + if (err) { + rev->error = 1; + } + + ngx_log_error(NGX_LOG_INFO, c->log, err, + "client closed prematurely connection"); + + ngx_http_close_request(r, 0); + + return; } 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 @@ -77,6 +77,7 @@ #define NGX_HTTP_REQUEST_TIME_OUT 408 #define NGX_HTTP_CONFLICT 409 #define NGX_HTTP_LENGTH_REQUIRED 411 +#define NGX_HTTP_PRECONDITION_FAILED 412 #define NGX_HTTP_REQUEST_ENTITY_TOO_LARGE 413 #define NGX_HTTP_REQUEST_URI_TOO_LARGE 414 #define NGX_HTTP_UNSUPPORTED_MEDIA_TYPE 415 @@ -193,6 +194,7 @@ typedef struct { #if (NGX_HTTP_DAV) ngx_table_elt_t *depth; ngx_table_elt_t *destination; + ngx_table_elt_t *overwrite; ngx_table_elt_t *date; #endif 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 @@ -74,13 +74,13 @@ ngx_http_read_client_request_body(ngx_ht tf->persistent = r->request_body_in_persistent_file; if (r->request_body_file_group_access) { - tf->mode = 0660; + tf->access = 0660; } rb->temp_file = tf; if (ngx_create_temp_file(&tf->file, tf->path, tf->pool, - tf->persistent, tf->mode) + tf->persistent, tf->access) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; @@ -163,6 +163,8 @@ ngx_http_read_client_request_body(ngx_ht /* the whole request body may be placed in r->header_in */ + rb->to_write = rb->bufs; + r->read_event_handler = ngx_http_read_client_request_body_handler; return ngx_http_do_read_client_request_body(r); @@ -400,7 +402,7 @@ ngx_http_write_request_body(ngx_http_req tf->persistent = r->request_body_in_persistent_file; if (r->request_body_file_group_access) { - tf->mode = 0660; + tf->access = 0660; } rb->temp_file = tf; diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c --- a/src/http/ngx_http_special_response.c +++ b/src/http/ngx_http_special_response.c @@ -139,6 +139,14 @@ static char error_411_page[] = ; +static char error_412_page[] = +"" CRLF +"412 Precondition Failed" CRLF +"" CRLF +"

412 Precondition Failed

" CRLF +; + + static char error_413_page[] = "" CRLF "413 Request Entity Too Large" CRLF @@ -274,7 +282,7 @@ static ngx_str_t error_pages[] = { ngx_string(error_409_page), ngx_string(error_410_page), ngx_string(error_411_page), - ngx_null_string, /* 412 */ + ngx_string(error_412_page), ngx_string(error_413_page), ngx_string(error_414_page), ngx_string(error_415_page), 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 @@ -569,8 +569,11 @@ ngx_http_upstream_connect(ngx_http_reque } } - if (r->request_body && r->request_body->temp_file && r == r->main) { - + if (r->request_body + && r->request_body->buf + && r->request_body->temp_file + && r == r->main) + { /* * the r->request_body->buf can be reused for one request only, * the subrequests should allocate their own temporay bufs @@ -1700,7 +1703,7 @@ ngx_http_upstream_process_non_buffered_b } } - if (downstream->write->active) { + if (downstream->write->active && !downstream->write->ready) { ngx_add_timer(downstream->write, clcf->send_timeout); } else if (downstream->write->timer_set) { @@ -1712,7 +1715,7 @@ ngx_http_upstream_process_non_buffered_b return; } - if (upstream->read->active) { + if (upstream->read->active && !upstream->read->ready) { ngx_add_timer(upstream->read, u->conf->read_timeout); } else if (upstream->read->timer_set) { diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c --- a/src/os/unix/ngx_files.c +++ b/src/os/unix/ngx_files.c @@ -112,11 +112,12 @@ ngx_write_file(ngx_file_t *file, u_char ngx_fd_t -ngx_open_tempfile(u_char *name, ngx_uint_t persistent, ngx_uint_t mode) +ngx_open_tempfile(u_char *name, ngx_uint_t persistent, ngx_uint_t access) { ngx_fd_t fd; - fd = open((const char *) name, O_CREAT|O_EXCL|O_RDWR, mode ? mode : 0600); + fd = open((const char *) name, O_CREAT|O_EXCL|O_RDWR, + access ? access : 0600); if (fd != -1 && !persistent) { unlink((const char *) name); diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h --- a/src/os/unix/ngx_files.h +++ b/src/os/unix/ngx_files.h @@ -17,17 +17,20 @@ -#define ngx_open_file(name, access, create) \ - open((const char *) name, access|create, 0644) +#define ngx_open_file(name, mode, create, access) \ + open((const char *) name, mode|create, access) #define ngx_open_file_n "open()" #define NGX_FILE_RDONLY O_RDONLY +#define NGX_FILE_WRONLY O_WRONLY #define NGX_FILE_RDWR O_RDWR #define NGX_FILE_CREATE_OR_OPEN O_CREAT #define NGX_FILE_OPEN 0 #define NGX_FILE_TRUNCATE O_TRUNC #define NGX_FILE_APPEND O_APPEND +#define NGX_FILE_DEFAULT_ACCESS 0644 + #define ngx_close_file close #define ngx_close_file_n "close()" @@ -38,7 +41,7 @@ ngx_fd_t ngx_open_tempfile(u_char *name, ngx_uint_t persistent, - ngx_uint_t mode); + ngx_uint_t access); #define ngx_open_tempfile_n "open()" @@ -52,7 +55,12 @@ ssize_t ngx_write_chain_to_file(ngx_file off_t offset, ngx_pool_t *pool); +#define ngx_read_fd read +#define ngx_read_fd_n "read()" + #define ngx_write_fd write +#define ngx_write_fd_n "write()" + #define ngx_linefeed(p) *p++ = LF; #define NGX_LINEFEED_SIZE 1 @@ -79,6 +87,7 @@ ngx_int_t ngx_set_file_time(u_char *name #define ngx_is_file(sb) (S_ISREG((sb)->st_mode)) #define ngx_is_link(sb) (S_ISLNK((sb)->st_mode)) #define ngx_is_exec(sb) ((sb)->st_mode & S_IXUSR) +#define ngx_file_access(sb) ((sb)->st_mode & 0777) #define ngx_file_size(sb) (sb)->st_size #define ngx_file_mtime(sb) (sb)->st_mtime #define ngx_file_uniq(sb) (sb)->st_ino @@ -126,6 +135,7 @@ ngx_int_t ngx_open_dir(ngx_str_t *name, #define ngx_de_is_dir(dir) (S_ISDIR((dir)->info.st_mode)) #define ngx_de_is_file(dir) (S_ISREG((dir)->info.st_mode)) #define ngx_de_is_link(dir) (S_ISLNK((dir)->info.st_mode)) +#define ngx_de_access(dir) (((dir)->info.st_mode) & 0777) #define ngx_de_size(dir) (dir)->info.st_size #define ngx_de_mtime(dir) (dir)->info.st_mtime