# HG changeset patch # User Igor Sysoev # Date 1101934800 -10800 # Node ID 8b6db3bda591dd2973db406e56b804aa56229af2 # Parent 4eeb9cfef970521281af55e050113b4ba007c305 nginx 0.1.11 *) Feature: the worker_priority directive. *) Change: both tcp_nopush and tcp_nodelay directives affect the transferred response. *) Bugfix: nginx did not call initgroups(). Thanks to Andrew Sitnikov and Andrei Nigmatulin. *) Change: now the ngx_http_autoindex_module shows the file size in the bytes. *) Bugfix: the ngx_http_autoindex_module returned the 500 error if the broken symlink was in a directory. *) Bugfix: the files bigger than 4G could not be transferred using sendfile. *) Bugfix: if the backend was resolved to several backends and there was an error while the response waiting then process may got caught in an endless loop. *) Bugfix: the worker process may exit with the "unknown cycle" message when the /dev/poll method was used. *) Bugfix: "close() channel failed" errors. *) Bugfix: the autodetection of the "nobody" and "nogroup" groups. *) Bugfix: the send_lowat directive did not work on Linux. *) Bugfix: the segmentation fault occurred if there was no events section in configuration. *) Bugfix: nginx could not be built on OpenBSD. *) Bugfix: the double slashes in "://" in the URI were converted to ":/". diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,43 @@ + +Changes with nginx 0.1.11 02 Dec 2004 + + *) Feature: the worker_priority directive. + + *) Change: both tcp_nopush and tcp_nodelay directives affect the + transferred response. + + *) Bugfix: nginx did not call initgroups(). + Thanks to Andrew Sitnikov and Andrei Nigmatulin. + + *) Change: now the ngx_http_autoindex_module shows the file size in the + bytes. + + *) Bugfix: the ngx_http_autoindex_module returned the 500 error if the + broken symlink was in a directory. + + *) Bugfix: the files bigger than 4G could not be transferred using + sendfile. + + *) Bugfix: if the backend was resolved to several backends and there was + an error while the response waiting then process may got caught in an + endless loop. + + *) Bugfix: the worker process may exit with the "unknown cycle" message + when the /dev/poll method was used. + + *) Bugfix: "close() channel failed" errors. + + *) Bugfix: the autodetection of the nobody and nogroup groups. + + *) Bugfix: the send_lowat directive did not work on Linux. + + *) Bugfix: the segmentation fault occurred if there was no events section + in configuration. + + *) Bugfix: nginx could not be built on OpenBSD. + + *) Bugfix: the double slashes in "://" in the URI were converted to ":/". + Changes with nginx 0.1.10 26 Nov 2004 @@ -36,8 +76,8 @@ Changes with nginx 0.1.8 Changes with nginx 0.1.7 12 Nov 2004 - *) Bugfix: on FreeBSD the segmentation fault may occure if the size of - the transferred file was changed; bug appeared in 0.1.5. + *) Bugfix: on FreeBSD the segmentation fault may occur if the size of the + transferred file was changed; bug appeared in 0.1.5. Changes with nginx 0.1.6 11 Nov 2004 diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,3 +1,41 @@ + +Изменения в nginx 0.1.11 02.12.2004 + + *) Добавление: директива worker_priority. + + *) Изменение: под FreeBSD директивы tcp_nopush и tcp_nodelay вместе + влияют на передачу ответа. + + *) Исправление: nginx не вызывал initgroups(). + Спасибо Андрею Ситникову и Андрею Нигматулину. + + *) Изменение: ngx_http_auto_index_module теперь выдаёт размер файлов в + байтах. + + *) Исправление: ngx_http_auto_index_module возвращал ошибку 500, если в + каталоге есть битый symlink. + + *) Исправление: файлы больше 4G не передавались с использованием sendfile. + + *) Исправление: если бэкенд резолвился в несколько адресов и при ожидании + от него ответа происходила ошибка, то процесс зацикливался. + + *) Исправление: при использовании метода /dev/poll рабочий процесс мог + завершиться с сообщением "unknown cycle". + + *) Исправление: ошибки "close() channel failed". + + *) Исправление: автоматическое определение групп nobody и nogroup. + + *) Исправление: директива send_lowat не работала на Linux. + + *) Исправление: если в конфигурации не было раздела events, то происходил + segmentation fault. + + *) Исправление: nginx не собирался под OpenBSD. + + *) Исправление: двойные слэшы в "://" в URI превращались в ":/". + Изменения в nginx 0.1.10 26.11.2004 diff --git a/auto/modules b/auto/modules --- a/auto/modules +++ b/auto/modules @@ -45,6 +45,11 @@ if [ $NGX_TEST_BUILD_RTSIG = YES ]; then CORE_SRCS="$CORE_SRCS $RTSIG_SRCS" fi +if [ $NGX_TEST_BUILD_SOLARIS_SENDFILEV = YES ]; then + have=NGX_TEST_BUILD_SOLARIS_SENDFILEV . auto/have + CORE_SRCS="$CORE_SRCS $SOLARIS_SENDFILEV_SRCS" +fi + # the filter order is important # ngx_http_write_filter diff --git a/auto/options b/auto/options --- a/auto/options +++ b/auto/options @@ -25,6 +25,7 @@ CPU=NO NGX_TEST_BUILD_DEVPOLL=NO NGX_TEST_BUILD_EPOLL=NO NGX_TEST_BUILD_RTSIG=NO +NGX_TEST_BUILD_SOLARIS_SENDFILEV=NO NGX_PLATFORM= NGX_WINE= @@ -146,6 +147,7 @@ do --test-build-devpoll) NGX_TEST_BUILD_DEVPOLL=YES ;; --test-build-epoll) NGX_TEST_BUILD_EPOLL=YES ;; --test-build-rtsig) NGX_TEST_BUILD_RTSIG=YES ;; + --test-build-solaris-sendfilev) NGX_TEST_BUILD_SOLARIS_SENDFILEV=YES ;; *) echo "$0: error: invalid option \"$option\"" @@ -212,11 +214,6 @@ if test -z "$NGX_PREFIX"; then fi -if test -z "$NGX_GROUP"; then - NGX_GROUP=NGX_USER -fi - - case ".$NGX_SBIN_PATH" in ./*) ;; diff --git a/auto/os/conf b/auto/os/conf --- a/auto/os/conf +++ b/auto/os/conf @@ -47,7 +47,26 @@ if [ $NGX_PLATFORM != win32 ]; then if test -z "$NGX_USER"; then NGX_USER=nobody - NGX_GROUP=nobody + fi + + if [ -z "$NGX_GROUP" -a $NGX_USER = nobody ] ; then + if grep nobody /etc/group 2>&1 >/dev/null; then + echo "checking for nobody group ... found" + NGX_GROUP=nobody + else + echo "checking for nobody group ... not found" + + if grep nogroup /etc/group 2>&1 >/dev/null; then + echo "checking for nogroup group ... found" + NGX_GROUP=nogroup + else + echo "checking for nogroup group ... not found" + NGX_GROUP=nobody + fi + fi + + else + NGX_GROUP=$NGX_USER fi diff --git a/auto/os/linux b/auto/os/linux --- a/auto/os/linux +++ b/auto/os/linux @@ -21,12 +21,6 @@ ngx_spacer=' CC_AUX_FLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64" -if test -z "$NGX_USER"; then - NGX_USER=nobody - NGX_GROUP=nogroup -fi - - # Linux kernel version version=`grep "#define LINUX_VERSION_CODE" /usr/include/linux/version.h \ diff --git a/auto/types/value b/auto/types/value --- a/auto/types/value +++ b/auto/types/value @@ -7,3 +7,5 @@ cat << END >> $NGX_AUTO_CONFIG_H #ifndef $ngx_param #define $ngx_param $ngx_value #endif + +END diff --git a/auto/unix b/auto/unix --- a/auto/unix +++ b/auto/unix @@ -43,31 +43,15 @@ ngx_type="rlim_t"; ngx_types="int"; . au . auto/endianess - -# printf() formats +ngx_type="size_t"; . auto/types/sizeof +ngx_param=MAX_SIZE_T_VALUE; ngx_value=$ngx_max_value; . auto/types/value -#CC_WARN=$CC_STRONG -#ngx_fmt_collect=no -# -#ngx_fmt_name=OFF_T_FMT; ngx_type="off_t"; . auto/types/sizeof -ngx_param=OFF_T_MAX_VALUE; ngx_value=$ngx_max_value; . auto/types/value -#eval ngx_formats=\${ngx_${ngx_size}_fmt}; . auto/fmt/fmt -# -#ngx_fmt_name=TIME_T_FMT; ngx_type="time_t"; . auto/types/sizeof +ngx_type="off_t"; . auto/types/sizeof +ngx_param=MAX_OFF_T_VALUE; ngx_value=$ngx_max_value; . auto/types/value + +ngx_type="time_t"; . auto/types/sizeof ngx_param=TIME_T_SIZE; ngx_value=$ngx_size; . auto/types/value ngx_param=TIME_T_LEN; ngx_value=$ngx_max_len; . auto/types/value -#eval ngx_formats=\${ngx_${ngx_size}_fmt}; . auto/fmt/fmt -# -#ngx_fmt_name=SIZE_T_FMT; ngx_type="size_t"; . auto/types/sizeof -#eval ngx_formats=\${ngx_${ngx_size}_fmt}; . auto/fmt/fmt -# -#ngx_fmt_name=SIZE_T_X_FMT; . auto/fmt/xfmt -# -#ngx_fmt_name=PID_T_FMT; ngx_type="pid_t"; . auto/types/sizeof -#eval ngx_formats=\${ngx_${ngx_size}_fmt}; . auto/fmt/fmt -# -#ngx_fmt_name=RLIM_T_FMT; ngx_type="rlim_t"; . auto/types/sizeof -#eval ngx_formats=\${ngx_${ngx_size}_fmt}; . auto/fmt/fmt # syscalls, libc calls and some features diff --git a/src/core/nginx.c b/src/core/nginx.c --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -16,6 +16,7 @@ static ngx_int_t ngx_save_argv(ngx_cycle static void *ngx_core_module_create_conf(ngx_cycle_t *cycle); static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf); static char *ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static ngx_conf_enum_t ngx_debug_points[] = { @@ -80,6 +81,13 @@ static ngx_command_t ngx_core_commands[ 0, NULL }, + { ngx_string("worker_priority"), + NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, + ngx_set_priority, + 0, + 0, + NULL }, + { ngx_string("pid"), NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, @@ -447,6 +455,7 @@ static void *ngx_core_module_create_conf * * ccf->pid = NULL; * ccf->newpid = NULL; + * ccf->priority = 0; */ ccf->daemon = NGX_CONF_UNSET; ccf->master = NGX_CONF_UNSET; @@ -494,6 +503,7 @@ static char *ngx_core_module_init_conf(n return NGX_CONF_ERROR; } + ccf->username = NGX_USER; ccf->user = pwd->pw_uid; grp = getgrnam(NGX_GROUP); @@ -562,6 +572,8 @@ static char *ngx_set_user(ngx_conf_t *cf value = (ngx_str_t *) cf->args->elts; + ccf->username = (char *) value[1].data; + pwd = getpwnam((const char *) value[1].data); if (pwd == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, @@ -586,3 +598,42 @@ static char *ngx_set_user(ngx_conf_t *cf #endif } + + +static char *ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_core_conf_t *ccf = conf; + + ngx_str_t *value; + ngx_uint_t n, minus; + + if (ccf->priority != 0) { + return "is duplicate"; + } + + value = cf->args->elts; + + if (value[1].data[0] == '-') { + n = 1; + minus = 1; + + } else if (value[1].data[0] == '+') { + n = 1; + minus = 0; + + } else { + n = 0; + minus = 0; + } + + ccf->priority = ngx_atoi(&value[1].data[n], value[1].len - n); + if (ccf->priority == NGX_ERROR) { + return "invalid number"; + } + + if (minus) { + ccf->priority = -ccf->priority; + } + + return NGX_CONF_OK; +} 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.10" +#define NGINX_VER "nginx/0.1.11" #define NGINX_VAR "NGINX" #define NGX_NEWPID_EXT ".newbin" diff --git a/src/core/ngx_buf.h b/src/core/ngx_buf.h --- a/src/core/ngx_buf.h +++ b/src/core/ngx_buf.h @@ -109,8 +109,8 @@ typedef struct { ((b->flush || b->last_buf) && !ngx_buf_in_memory(b) && !b->in_file) #define ngx_buf_size(b) \ - (ngx_buf_in_memory(b) ? (size_t) (b->last - b->pos): \ - (size_t) (b->file_last - b->file_pos)) + (ngx_buf_in_memory(b) ? (off_t) (b->last - b->pos): \ + (b->file_last - b->file_pos)) ngx_buf_t *ngx_create_temp_buf(ngx_pool_t *pool, size_t size); ngx_chain_t *ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs); diff --git a/src/core/ngx_config.h b/src/core/ngx_config.h --- a/src/core/ngx_config.h +++ b/src/core/ngx_config.h @@ -39,6 +39,11 @@ #endif +#ifndef NGX_HAVE_SO_SNDLOWAT +#define NGX_HAVE_SO_SNDLOWAT 1 +#endif + + #if !(NGX_WIN32) #define ngx_signal_helper(n) SIG##n 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 @@ -50,7 +50,6 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t ngx_open_file_t *file; ngx_listening_t *ls, *nls; ngx_core_conf_t *ccf; - ngx_event_conf_t *ecf; ngx_core_module_t *module; log = old_cycle->log; @@ -434,12 +433,6 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t } - ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module); - - ngx_log_error(NGX_LOG_INFO, cycle->log, 0, - "using the \"%s\" event method", ecf->name); - - /* close and delete stuff that lefts from an old cycle */ /* close the unneeded listening sockets */ diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h --- a/src/core/ngx_cycle.h +++ b/src/core/ngx_cycle.h @@ -17,51 +17,54 @@ struct ngx_cycle_s { - void ****conf_ctx; - ngx_pool_t *pool; + void ****conf_ctx; + ngx_pool_t *pool; - ngx_log_t *log; - ngx_log_t *new_log; + ngx_log_t *log; + ngx_log_t *new_log; - ngx_array_t listening; - ngx_array_t pathes; - ngx_list_t open_files; + ngx_array_t listening; + ngx_array_t pathes; + ngx_list_t open_files; - ngx_uint_t connection_n; - ngx_connection_t *connections; - ngx_event_t *read_events; - ngx_event_t *write_events; + ngx_uint_t connection_n; + ngx_connection_t *connections; + ngx_event_t *read_events; + ngx_event_t *write_events; - ngx_cycle_t *old_cycle; + ngx_cycle_t *old_cycle; - ngx_str_t conf_file; - ngx_str_t root; + ngx_str_t conf_file; + ngx_str_t root; }; typedef struct { - ngx_flag_t daemon; - ngx_flag_t master; + ngx_flag_t daemon; + ngx_flag_t master; - ngx_int_t worker_processes; - ngx_int_t debug_points; + ngx_int_t worker_processes; + ngx_int_t debug_points; - ngx_uid_t user; - ngx_gid_t group; + int priority; - ngx_str_t pid; - ngx_str_t newpid; + char *username; + ngx_uid_t user; + ngx_gid_t group; + + ngx_str_t pid; + ngx_str_t newpid; #if (NGX_THREADS) - ngx_int_t worker_threads; - size_t thread_stack_size; + ngx_int_t worker_threads; + size_t thread_stack_size; #endif } ngx_core_conf_t; typedef struct { - ngx_pool_t *pool; /* pcre's malloc() pool */ + ngx_pool_t *pool; /* pcre's malloc() pool */ } ngx_core_tls_t; diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c --- a/src/core/ngx_output_chain.c +++ b/src/core/ngx_output_chain.c @@ -28,7 +28,8 @@ static ngx_int_t ngx_output_chain_copy_b ngx_int_t ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in) { int rc, last; - size_t size, bsize; + off_t bsize; + size_t size; ngx_chain_t *cl, *out, **last_out; if (ctx->in == NULL && ctx->busy == NULL) { @@ -81,6 +82,8 @@ ngx_int_t ngx_output_chain(ngx_output_ch ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0, "zero size buf"); + ngx_debug_point(); + ctx->in = ctx->in->next; continue; @@ -118,18 +121,18 @@ ngx_int_t ngx_output_chain(ngx_output_ch if (ctx->in->buf->last_buf) { - if (bsize < ctx->bufs.size) { + if (bsize < (off_t) ctx->bufs.size) { /* * allocate small temp buf for the small last buf * or its small last part */ - size = bsize; + size = (size_t) bsize; } else if (ctx->bufs.num == 1 - && (bsize < ctx->bufs.size - + (ctx->bufs.size >> 2))) + && (bsize < (off_t) (ctx->bufs.size + + (ctx->bufs.size >> 2)))) { /* * allocate a temp buf that equals @@ -137,7 +140,7 @@ ngx_int_t ngx_output_chain(ngx_output_ch * than 1.25 of bufs.size and a temp buf is single */ - size = bsize; + size = (size_t) bsize; } } @@ -306,12 +309,12 @@ static ngx_int_t ngx_output_chain_add_co static ngx_int_t ngx_output_chain_copy_buf(ngx_buf_t *dst, ngx_buf_t *src, ngx_uint_t sendfile) { - size_t size; + off_t size; ssize_t n; size = ngx_buf_size(src); - if (size > (size_t) (dst->end - dst->pos)) { + if (size > dst->end - dst->pos) { size = dst->end - dst->pos; } @@ -324,9 +327,9 @@ static ngx_int_t ngx_output_chain_copy_b #endif if (ngx_buf_in_memory(src)) { - ngx_memcpy(dst->pos, src->pos, size); - src->pos += size; - dst->last += size; + ngx_memcpy(dst->pos, src->pos, (size_t) size); + src->pos += (size_t) size; + dst->last += (size_t) size; if (src->in_file) { @@ -351,7 +354,7 @@ static ngx_int_t ngx_output_chain_copy_b } } else { - n = ngx_read_file(src->file, dst->pos, size, src->file_pos); + n = ngx_read_file(src->file, dst->pos, (size_t) size, src->file_pos); if (n == NGX_ERROR) { return n; @@ -363,9 +366,9 @@ static ngx_int_t ngx_output_chain_copy_b } #endif - if ((size_t) n != size) { + if (n != size) { ngx_log_error(NGX_LOG_ALERT, src->file->log, 0, - ngx_read_file_n " reads only %z of %uz from file", + ngx_read_file_n " reads only %z of %O from file", n, size); if (n == 0) { return NGX_ERROR; @@ -399,10 +402,19 @@ ngx_int_t ngx_chain_writer(void *data, n { ngx_chain_writer_ctx_t *ctx = data; + off_t size; ngx_chain_t *cl; - for (/* void */; in; in = in->next) { + for (size = 0; in; in = in->next) { + +#if 1 + if (ngx_buf_size(in->buf) == 0 && !ngx_buf_special(in->buf)) { + ngx_debug_point(); + } +#endif + + size += ngx_buf_size(in->buf); ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->connection->log, 0, "chain writer buf size: %uz", ngx_buf_size(in->buf)); @@ -419,6 +431,23 @@ ngx_int_t ngx_chain_writer(void *data, n ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->connection->log, 0, "chain writer in: %p", ctx->out); + for (cl = ctx->out; cl; cl = cl->next) { + +#if 1 + + if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) { + ngx_debug_point(); + } + +#endif + + size += ngx_buf_size(cl->buf); + } + + if (size == 0) { + return NGX_OK; + } + ctx->out = ngx_send_chain(ctx->connection, ctx->out, ctx->limit); ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->connection->log, 0, diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -30,7 +30,7 @@ u_char *ngx_cpystrn(u_char *dst, u_char /* * supported formats: - * %[0][width]O off_t + * %[0][width][x][X]O off_t * %[0][width]T time_t * %[0][width][u][x|X]z ssize_t/size_t * %[0][width][u][x|X]d int/u_int diff --git a/src/event/modules/ngx_devpoll_module.c b/src/event/modules/ngx_devpoll_module.c --- a/src/event/modules/ngx_devpoll_module.c +++ b/src/event/modules/ngx_devpoll_module.c @@ -435,6 +435,16 @@ int ngx_devpoll_process_events(ngx_cycle c = &ngx_cycle->connections[event_list[i].fd]; if (c->fd == -1) { + if (ngx_cycle->read_events[event_list[i].fd].closed) { + continue; + } + + ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unexpected event"); + continue; + } + +#if 0 + if (c->fd == -1) { old_cycle = ngx_old_cycles.elts; for (j = 0; j < ngx_old_cycles.nelts; j++) { if (old_cycle[j] == NULL) { @@ -451,6 +461,7 @@ int ngx_devpoll_process_events(ngx_cycle ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "unknown cycle"); exit(1); } +#endif ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "devpoll: fd:%d, ev:%04Xd, rev:%04Xd", diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -174,10 +174,25 @@ static ngx_int_t ngx_event_module_init(n { #if !(NGX_WIN32) - size_t size; - char *shared; - ngx_core_conf_t *ccf; - ngx_event_conf_t *ecf; + size_t size; + void ***cf; + char *shared; + ngx_core_conf_t *ccf; + ngx_event_conf_t *ecf; + + cf = ngx_get_conf(cycle->conf_ctx, ngx_events_module); + + if (cf == NULL) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, + "no \"events\" section in configuration"); + return NGX_ERROR; + } + + ecf = (*cf)[ngx_event_core_module.ctx_index]; + + ngx_log_error(NGX_LOG_INFO, cycle->log, 0, + "using the \"%s\" event method", ecf->name); + ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); @@ -185,8 +200,6 @@ static ngx_int_t ngx_event_module_init(n return NGX_OK; } - ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module); - /* TODO: 128 is cache line size */ diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c --- a/src/event/ngx_event_connect.c +++ b/src/event/ngx_event_connect.c @@ -81,9 +81,12 @@ ngx_int_t ngx_event_connect_peer(ngx_pee for ( ;; ) { peer = &pc->peers->peers[pc->cur_peer]; - if (peer->fails <= pc->peers->max_fails - || (now - peer->accessed > pc->peers->fail_timeout)) - { + if (peer->fails <= pc->peers->max_fails) { + break; + } + + if (now - peer->accessed > pc->peers->fail_timeout) { + peer->fails = 0; break; } 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 @@ -9,7 +9,9 @@ #include +static void ngx_ssl_write_handler(ngx_event_t *wev); static ssize_t ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size); +static void ngx_ssl_read_handler(ngx_event_t *rev); ngx_int_t ngx_ssl_init(ngx_log_t *log) @@ -69,6 +71,25 @@ ssize_t ngx_ssl_recv(ngx_connection_t *c ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n); if (n > 0) { + if (c->ssl->saved_write_handler) { + + c->write->event_handler = c->ssl->saved_write_handler; + c->ssl->saved_write_handler = NULL; + c->write->ready = 1; + + if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { + return NGX_ERROR; + } + + if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { + return NGX_ERROR; + } + + ngx_post_event(c->write); + + ngx_mutex_unlock(ngx_posted_events_mutex); + } + return n; } @@ -93,13 +114,27 @@ ssize_t ngx_ssl_recv(ngx_connection_t *c if (sslerr == SSL_ERROR_WANT_WRITE) { ngx_log_error(NGX_LOG_ALERT, c->log, err, "SSL wants to write%s", handshake); - return NGX_ERROR; -#if 0 + + c->write->ready = 0; + + if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { + return NGX_ERROR; + } + + /* + * we do not set the timer because there is already the read event timer + */ + + if (c->ssl->saved_write_handler == NULL) { + c->ssl->saved_write_handler = c->write->event_handler; + c->write->event_handler = ngx_ssl_write_handler; + } + return NGX_AGAIN; -#endif } c->ssl->no_rcv_shut = 1; + c->ssl->no_send_shut = 1; if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) { ngx_log_error(NGX_LOG_INFO, c->log, err, @@ -115,9 +150,18 @@ ssize_t ngx_ssl_recv(ngx_connection_t *c } +static void ngx_ssl_write_handler(ngx_event_t *wev) +{ + ngx_connection_t *c; + + c = wev->data; + c->read->event_handler(c->read); +} + + /* * OpenSSL has no SSL_writev() so we copy several bufs into our 16K buffer - * before SSL_write() call to decrease a SSL overhead. + * before the SSL_write() call to decrease a SSL overhead. * * Besides for protocols such as HTTP it is possible to always buffer * the output to decrease a SSL overhead some more. @@ -155,6 +199,14 @@ ngx_chain_t *ngx_ssl_send_chain(ngx_conn return in; } + + /* the maximum limit size is the maximum uint32_t value - the page size */ + + if (limit == 0 || limit > NGX_MAX_UINT32_VALUE - ngx_pagesize) { + limit = NGX_MAX_UINT32_VALUE - ngx_pagesize; + } + + send = 0; flush = (in == NULL) ? 1 : 0; @@ -252,6 +304,25 @@ static ssize_t ngx_ssl_write(ngx_connect ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_write: %d", n); if (n > 0) { + if (c->ssl->saved_read_handler) { + + c->read->event_handler = c->ssl->saved_read_handler; + c->ssl->saved_read_handler = NULL; + c->read->ready = 1; + + if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { + return NGX_ERROR; + } + + if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { + return NGX_ERROR; + } + + ngx_post_event(c->read); + + ngx_mutex_unlock(ngx_posted_events_mutex); + } + return n; } @@ -277,13 +348,28 @@ static ssize_t ngx_ssl_write(ngx_connect ngx_log_error(NGX_LOG_ALERT, c->log, err, "SSL wants to read%s", handshake); - return NGX_ERROR; -#if 0 + + c->read->ready = 0; + + if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { + return NGX_ERROR; + } + + /* + * we do not set the timer because there is already + * the write event timer + */ + + if (c->ssl->saved_read_handler == NULL) { + c->ssl->saved_read_handler = c->read->event_handler; + c->read->event_handler = ngx_ssl_read_handler; + } + return NGX_AGAIN; -#endif } c->ssl->no_rcv_shut = 1; + c->ssl->no_send_shut = 1; ngx_ssl_error(NGX_LOG_ALERT, c->log, err, "SSL_write() failed"); @@ -291,21 +377,42 @@ static ssize_t ngx_ssl_write(ngx_connect } +static void ngx_ssl_read_handler(ngx_event_t *rev) +{ + ngx_connection_t *c; + + c = rev->data; + c->write->event_handler(c->write); +} + + ngx_int_t ngx_ssl_shutdown(ngx_connection_t *c) { - int n, sslerr; + int n, sslerr, mode; ngx_uint_t again; - if (c->timedout) { - SSL_set_shutdown(c->ssl->ssl, SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN); + if (!c->ssl->shutdown_set) { + + /* it seems that SSL_set_shutdown() could be called once only */ + + if (c->read->timedout) { + mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN; - } else { - if (c->ssl->no_rcv_shut) { - SSL_set_shutdown(c->ssl->ssl, SSL_RECEIVED_SHUTDOWN); + } else { + mode = 0; + + if (c->ssl->no_rcv_shut) { + mode = SSL_RECEIVED_SHUTDOWN; + } + + if (c->ssl->no_send_shut) { + mode |= SSL_SENT_SHUTDOWN; + } } - if (c->ssl->no_send_shut) { - SSL_set_shutdown(c->ssl->ssl, SSL_SENT_SHUTDOWN); + if (mode) { + SSL_set_shutdown(c->ssl->ssl, mode); + c->ssl->shutdown_set = 1; } } @@ -319,17 +426,17 @@ ngx_int_t ngx_ssl_shutdown(ngx_connectio ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n); + if (n == 1 || (n == 0 && c->read->timedout)) { + SSL_free(c->ssl->ssl); + c->ssl = NULL; + return NGX_OK; + } + if (n == 0) { again = 1; break; } - if (n == 1) { - SSL_free(c->ssl->ssl); - c->ssl = NULL; - return NGX_OK; - } - break; } @@ -342,7 +449,7 @@ ngx_int_t ngx_ssl_shutdown(ngx_connectio if (again || sslerr == SSL_ERROR_WANT_READ) { - ngx_add_timer(c->read, 10000); + ngx_add_timer(c->read, 30000); if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { return NGX_ERROR; diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -18,11 +18,13 @@ typedef struct { SSL *ssl; ngx_buf_t *buf; - ngx_event_handler_pt saved_handler; + ngx_event_handler_pt saved_read_handler; + ngx_event_handler_pt saved_write_handler; unsigned buffer:1; unsigned no_rcv_shut:1; unsigned no_send_shut:1; + unsigned shutdown_set:1; } ngx_ssl_t; @@ -48,10 +50,5 @@ ngx_int_t ngx_ssl_shutdown(ngx_connectio void ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...); -#define ngx_ssl_set_nosendshut(ssl) \ - if (ssl) { \ - ssl->no_send_shut = 1; \ - } - #endif /* _NGX_EVENT_OPENSSL_H_INCLUDED_ */ 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 @@ -379,7 +379,7 @@ ngx_int_t ngx_event_pipe_read_upstream(n ngx_int_t ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p) { - size_t bsize; + off_t bsize; ngx_uint_t flush; ngx_buf_t *b; ngx_chain_t *out, **ll, *cl, *tl; @@ -442,7 +442,7 @@ ngx_int_t ngx_event_pipe_write_to_downst } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, - "pipe write busy: %uz", bsize); + "pipe write busy: %O", bsize); out = NULL; ll = NULL; diff --git a/src/event/ngx_event_pipe.h b/src/event/ngx_event_pipe.h --- a/src/event/ngx_event_pipe.h +++ b/src/event/ngx_event_pipe.h @@ -62,7 +62,7 @@ struct ngx_event_pipe_s { ngx_bufs_t bufs; ngx_buf_tag_t tag; - size_t busy_size; + ssize_t busy_size; off_t read_length; diff --git a/src/http/modules/ngx_http_autoindex_handler.c b/src/http/modules/ngx_http_autoindex_handler.c --- a/src/http/modules/ngx_http_autoindex_handler.c +++ b/src/http/modules/ngx_http_autoindex_handler.c @@ -105,11 +105,10 @@ static u_char tail[] = static ngx_int_t ngx_http_autoindex_handler(ngx_http_request_t *r) { - u_char *last, scale; + u_char *last; size_t len; - off_t length; ngx_tm_t tm; - ngx_int_t rc, size; + ngx_int_t rc; ngx_uint_t i, level; ngx_err_t err; ngx_buf_t *b; @@ -307,7 +306,7 @@ static ngx_int_t ngx_http_autoindex_hand + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof(">") - 2 + sizeof("") - 1 + sizeof(" 28-Sep-1970 12:00 ") - 1 - + sizeof("1023G") - 1 + + 19 + 2; } @@ -383,44 +382,11 @@ static ngx_int_t ngx_http_autoindex_hand tm.ngx_tm_min); if (entry[i].dir) { - b->last = ngx_cpymem(b->last, " -", sizeof(" -") - 1); + b->last = ngx_cpymem(b->last, " -", + sizeof(" -") - 1); } else { - length = entry[i].size; - - if (length > 1024 * 1024 * 1024 - 1) { - size = (ngx_int_t) (length / (1024 * 1024 * 1024)); - if ((length % (1024 * 1024 * 1024)) - > (1024 * 1024 * 1024 / 2 - 1)) - { - size++; - } - scale = 'G'; - - } else if (length > 1024 * 1024 - 1) { - size = (ngx_int_t) (length / (1024 * 1024)); - if ((length % (1024 * 1024)) > (1024 * 1024 / 2 - 1)) { - size++; - } - scale = 'M'; - - } else if (length > 9999) { - size = (ngx_int_t) (length / 1024); - if (length % 1024 > 511) { - size++; - } - scale = 'K'; - - } else { - size = (ngx_int_t) length; - scale = ' '; - } - - b->last = ngx_sprintf(b->last, "%4i", size); - - if (scale != ' ') { - *b->last++ = scale; - } + b->last = ngx_sprintf(b->last, "%19O", entry[i].size); } *b->last++ = CR; diff --git a/src/http/modules/ngx_http_chunked_filter.c b/src/http/modules/ngx_http_chunked_filter.c --- a/src/http/modules/ngx_http_chunked_filter.c +++ b/src/http/modules/ngx_http_chunked_filter.c @@ -63,7 +63,7 @@ static ngx_int_t ngx_http_chunked_body_f ngx_chain_t *in) { u_char *chunk; - size_t size; + off_t size; ngx_buf_t *b; ngx_chain_t out, tail, *cl, *tl, **ll; @@ -106,13 +106,14 @@ static ngx_int_t ngx_http_chunked_body_f return NGX_ERROR; } - if (!(chunk = ngx_palloc(r->pool, sizeof("00000000" CRLF) - 1))) { + chunk = ngx_palloc(r->pool, sizeof("0000000000000000" CRLF) - 1); + if (chunk == NULL) { return NGX_ERROR; } b->temporary = 1; b->pos = chunk; - b->last = ngx_sprintf(chunk, "%xz" CRLF, size); + b->last = ngx_sprintf(chunk, "%xO" CRLF, size); out.buf = b; } diff --git a/src/http/modules/ngx_http_index_handler.c b/src/http/modules/ngx_http_index_handler.c --- a/src/http/modules/ngx_http_index_handler.c +++ b/src/http/modules/ngx_http_index_handler.c @@ -448,8 +448,7 @@ static char *ngx_http_index_merge_loc_co ngx_http_index_loc_conf_t *prev = parent; ngx_http_index_loc_conf_t *conf = child; - ngx_uint_t i; - ngx_str_t *index, *prev_index; + ngx_str_t *index; if (conf->max_index_len == 0) { if (prev->max_index_len != 0) { @@ -465,6 +464,8 @@ static char *ngx_http_index_merge_loc_co return NGX_CONF_OK; } +#if 0 + if (prev->max_index_len != 0) { prev_index = prev->indices.elts; @@ -476,6 +477,8 @@ static char *ngx_http_index_merge_loc_co } } +#endif + if (conf->max_index_len < prev->max_index_len) { conf->max_index_len = prev->max_index_len; } diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c --- a/src/http/modules/proxy/ngx_http_proxy_handler.c +++ b/src/http/modules/proxy/ngx_http_proxy_handler.c @@ -275,12 +275,9 @@ ngx_module_t ngx_http_proxy_module = { static ngx_http_log_op_name_t ngx_http_proxy_log_fmt_ops[] = { - { ngx_string("proxy"), /* STUB */ 100, - ngx_http_proxy_log_proxy_state }, - { ngx_string("proxy_cache_state"), sizeof("BYPASS") - 1, - ngx_http_proxy_log_cache_state }, - { ngx_string("proxy_reason"), sizeof("BPS") - 1, - ngx_http_proxy_log_reason }, + { ngx_string("proxy"), 0, ngx_http_proxy_log_proxy_state }, + { ngx_string("proxy_cache_state"), 0, ngx_http_proxy_log_cache_state }, + { ngx_string("proxy_reason"), 0, ngx_http_proxy_log_reason }, { ngx_null_string, 0, NULL } }; @@ -792,111 +789,180 @@ u_char *ngx_http_proxy_log_error(void *d static u_char *ngx_http_proxy_log_proxy_state(ngx_http_request_t *r, u_char *buf, uintptr_t data) { - ngx_http_proxy_ctx_t *p; + ngx_uint_t i; + ngx_http_proxy_ctx_t *p; + ngx_http_proxy_state_t *state; p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module); if (p == NULL) { + if (buf == NULL) { + return (u_char *) 1; + } + *buf = '-'; return buf + 1; } - if (p->state->cache_state == 0) { - *buf++ = '-'; - } else { - buf = ngx_cpymem(buf, cache_states[p->state->cache_state - 1].data, - cache_states[p->state->cache_state - 1].len); - } - - *buf++ = '/'; - - if (p->state->expired == 0) { - *buf++ = '-'; - - } else { - buf = ngx_sprintf(buf, "%T", p->state->expired); - } - - *buf++ = '/'; - - if (p->state->bl_time == 0) { - *buf++ = '-'; - - } else { - buf = ngx_sprintf(buf, "%T", p->state->bl_time); + if (buf == NULL) { + /* find the request line length */ + return (u_char *) (uintptr_t) (p->states.nelts * /* STUB */ 100); } - *buf++ = '/'; + + i = 0; + state = p->states.elts; - *buf++ = '*'; + for ( ;; ) { + if (state[i].cache_state == 0) { + *buf++ = '-'; - *buf++ = ' '; + } else { + buf = ngx_cpymem(buf, cache_states[state[i].cache_state - 1].data, + cache_states[state[i].cache_state - 1].len); + } - if (p->state->status == 0) { - *buf++ = '-'; + *buf++ = '/'; + + if (state[i].expired == 0) { + *buf++ = '-'; - } else { - buf = ngx_sprintf(buf, "%ui", p->state->status); - } + } else { + buf = ngx_sprintf(buf, "%T", state[i].expired); + } + + *buf++ = '/'; + + if (state[i].bl_time == 0) { + *buf++ = '-'; - *buf++ = '/'; + } else { + buf = ngx_sprintf(buf, "%T", state[i].bl_time); + } - if (p->state->reason == 0) { - *buf++ = '-'; + *buf++ = '/'; + + *buf++ = '*'; + + *buf++ = ' '; - } else { - buf = ngx_cpymem(buf, cache_reasons[p->state->reason - 1].data, - cache_reasons[p->state->reason - 1].len); - } + if (state[i].status == 0) { + *buf++ = '-'; + + } else { + buf = ngx_sprintf(buf, "%ui", state[i].status); + } - *buf++ = '/'; + *buf++ = '/'; + + if (state[i].reason == 0) { + *buf++ = '-'; + + } else { + buf = ngx_cpymem(buf, cache_reasons[state[i].reason - 1].data, + cache_reasons[state[i].reason - 1].len); + } - if (p->state->reason < NGX_HTTP_PROXY_CACHE_XAE) { - *buf++ = '-'; + *buf++ = '/'; + + if (state[i].reason < NGX_HTTP_PROXY_CACHE_XAE) { + *buf++ = '-'; + + } else { + buf = ngx_sprintf(buf, "%T", state[i].expires); + } - } else { - buf = ngx_sprintf(buf, "%T", p->state->expires); + *buf++ = ' '; + *buf++ = '*'; + + if (++i == p->states.nelts) { + return buf; + } + + *buf++ = ','; + *buf++ = ' '; } - - *buf++ = ' '; - *buf++ = '*'; - - return buf; } static u_char *ngx_http_proxy_log_cache_state(ngx_http_request_t *r, u_char *buf, uintptr_t data) { - ngx_http_proxy_ctx_t *p; + ngx_uint_t i; + ngx_http_proxy_ctx_t *p; + ngx_http_proxy_state_t *state; p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module); if (p == NULL || p->state->cache_state == 0) { + if (buf == NULL) { + return (u_char *) 1; + } + *buf = '-'; return buf + 1; } - return ngx_cpymem(buf, cache_states[p->state->cache_state - 1].data, - cache_states[p->state->cache_state - 1].len); + if (buf == NULL) { + /* find the request line length */ + return (u_char *) (p->states.nelts * sizeof("BYPASS") - 1); + } + + i = 0; + state = p->states.elts; + + for ( ;; ) { + buf = ngx_cpymem(buf, cache_states[state[i].cache_state - 1].data, + cache_states[state[i].cache_state - 1].len); + + if (++i == p->states.nelts) { + return buf; + } + + *buf++ = ','; + *buf++ = ' '; + } } static u_char *ngx_http_proxy_log_reason(ngx_http_request_t *r, u_char *buf, uintptr_t data) { - ngx_http_proxy_ctx_t *p; + ngx_uint_t i; + ngx_http_proxy_ctx_t *p; + ngx_http_proxy_state_t *state; p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module); if (p == NULL || p->state->reason == 0) { + if (buf == NULL) { + return (u_char *) 1; + } + *buf = '-'; return buf + 1; } - return ngx_cpymem(buf, cache_reasons[p->state->reason - 1].data, - cache_reasons[p->state->reason - 1].len); + if (buf == NULL) { + /* find the request line length */ + return (u_char *) (p->states.nelts * sizeof("BPS") - 1); + } + + i = 0; + state = p->states.elts; + + for ( ;; ) { + buf = ngx_cpymem(buf, cache_reasons[state[i].reason - 1].data, + cache_reasons[state[i].reason - 1].len); + + if (++i == p->states.nelts) { + return buf; + } + + *buf++ = ','; + *buf++ = ' '; + } } @@ -1387,10 +1453,9 @@ static char *ngx_http_proxy_parse_upstre static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data) { +#if (NGX_FREEBSD) ssize_t *np = data; -#if (NGX_FREEBSD) - if (*np >= ngx_freebsd_net_inet_tcp_sendspace) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"proxy_send_lowat\" must be less than %d " @@ -1401,6 +1466,7 @@ static char *ngx_http_proxy_lowat_check( } #elif !(NGX_HAVE_SO_SNDLOWAT) + ssize_t *np = data; ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "\"proxy_send_lowat\" is not supported, ignored"); diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c --- a/src/http/modules/proxy/ngx_http_proxy_upstream.c +++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c @@ -528,6 +528,7 @@ static void ngx_http_proxy_reinit_upstre { ngx_chain_t *cl; ngx_output_chain_ctx_t *output; + ngx_http_proxy_state_e state; /* reinit the request chain */ @@ -560,11 +561,17 @@ static void ngx_http_proxy_reinit_upstre /* add one more state */ + state = p->state->cache_state; + if (!(p->state = ngx_push_array(&p->states))) { ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } + ngx_memzero(p->state, sizeof(ngx_http_proxy_state_t)); + + p->state->cache_state = state; + p->status = 0; p->status_count = 0; } @@ -719,9 +726,9 @@ static void ngx_http_proxy_connect(ngx_h writer->out = NULL; writer->last = &writer->out; writer->connection = c; - writer->limit = OFF_T_MAX_VALUE; + writer->limit = 0; - if (p->upstream->peer.tries > 1 && p->request_sent) { + if (p->request_sent) { ngx_http_proxy_reinit_upstream(p); } @@ -803,13 +810,13 @@ static void ngx_http_proxy_send_request( p->request_sent ? NULL: p->request->request_body->bufs); + p->request_sent = 1; + if (rc == NGX_ERROR) { ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_ERROR); return; } - p->request_sent = 1; - if (c->write->timer_set) { ngx_del_timer(c->write); } diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h --- a/src/http/ngx_http_cache.h +++ b/src/http/ngx_http_cache.h @@ -97,6 +97,11 @@ typedef struct { } ngx_http_cache_t; +typedef struct { + ngx_path_t path; + ngx_str_t key; +} ngx_http_cache_ctx_t; + #define NGX_HTTP_CACHE_STALE 1 #define NGX_HTTP_CACHE_AGED 2 diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -1815,10 +1815,9 @@ static char *ngx_set_error_log(ngx_conf_ static char *ngx_http_lowat_check(ngx_conf_t *cf, void *post, void *data) { +#if (NGX_FREEBSD) ssize_t *np = data; -#if (NGX_FREEBSD) - if (*np >= ngx_freebsd_net_inet_tcp_sendspace) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"send_lowat\" must be less than %d " @@ -1829,6 +1828,7 @@ static char *ngx_http_lowat_check(ngx_co } #elif !(NGX_HAVE_SO_SNDLOWAT) + ssize_t *np = data; ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "\"send_lowat\" is not supported, ignored"); diff --git a/src/http/ngx_http_header_filter.c b/src/http/ngx_http_header_filter.c --- a/src/http/ngx_http_header_filter.c +++ b/src/http/ngx_http_header_filter.c @@ -252,9 +252,7 @@ static ngx_int_t ngx_http_header_filter( * Konqueror keeps the connection alive for about N seconds. */ - if (clcf->keepalive_header - && (r->headers_in.gecko || r->headers_in.konqueror)) - { + if (clcf->keepalive_header) { len += sizeof("Keep-Alive: timeout=") - 1 + TIME_T_LEN + 2; } @@ -384,9 +382,7 @@ static ngx_int_t ngx_http_header_filter( b->last = ngx_cpymem(b->last, "Connection: keep-alive" CRLF, sizeof("Connection: keep-alive" CRLF) - 1); - if (clcf->keepalive_header - && (r->headers_in.gecko || r->headers_in.konqueror)) - { + if (clcf->keepalive_header) { b->last = ngx_sprintf(b->last, "Keep-Alive: timeout=%T" CRLF, clcf->keepalive_header); } diff --git a/src/http/ngx_http_log_handler.c b/src/http/ngx_http_log_handler.c --- a/src/http/ngx_http_log_handler.c +++ b/src/http/ngx_http_log_handler.c @@ -166,7 +166,10 @@ ngx_int_t ngx_http_log_handler(ngx_http_ len++; #endif - ngx_test_null(line, ngx_palloc(r->pool, len), NGX_ERROR); + if (!(line = ngx_palloc(r->pool, len))) { + return NGX_ERROR; + } + p = line; for (i = 0; i < log[l].ops->nelts; i++) { diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -665,6 +665,8 @@ ngx_int_t ngx_http_parse_complex_uri(ngx u_char c, ch, decoded, *p, *u; enum { sw_usual = 0, + sw_colon, + sw_colon_slash, sw_slash, sw_dot, sw_dot_dot, @@ -730,8 +732,14 @@ ngx_int_t ngx_http_parse_complex_uri(ngx case '?': r->args_start = p; break; + case ':': + state = sw_colon; + *u++ = ch; + break; case '.': r->uri_ext = u + 1; + *u++ = ch; + break; default: *u++ = ch; break; @@ -739,6 +747,61 @@ ngx_int_t ngx_http_parse_complex_uri(ngx ch = *p++; break; + case sw_colon: + switch(ch) { +#if (NGX_WIN32) + case '\\': + state = sw_colon_slash; + *u++ = '/'; + break; +#endif + case '/': + state = sw_colon_slash; + *u++ = ch; + break; + case ':': + *u++ = ch; + break; + case '%': + quoted_state = state; + state = sw_quoted; + break; + default: + state = sw_usual; + *u++ = ch; + break; + } + ch = *p++; + break; + + case sw_colon_slash: + switch(ch) { +#if (NGX_WIN32) + case '\\': + state = sw_slash; + *u++ = '/'; + break; +#endif + case '/': + state = sw_slash; + *u++ = ch; + break; + case '.': + state = sw_dot; + *u++ = ch; + break; + case '%': + quoted_state = state; + state = sw_quoted; + break; + default: + state = sw_usual; + *u++ = ch; + break; + } + ch = *p++; + break; + case sw_slash: switch(ch) { #if (NGX_WIN32) 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 @@ -1190,8 +1190,9 @@ static ngx_int_t ngx_http_process_reques #if 0 /* MSIE ignores the SSL "close notify" alert */ - - ngx_ssl_set_nosendshut(r->connection->ssl); + if (c->ssl) { + r->connection->ssl->no_send_shut = 1; + } #endif } @@ -1269,7 +1270,7 @@ void ngx_http_finalize_request(ngx_http_ } if (r->connection->read->pending_eof) { -#if (NGX_KQUEUE) +#if (NGX_HAVE_KQUEUE) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, r->connection->read->kq_errno, "kevent() reported about an closed connection"); @@ -1702,24 +1703,26 @@ static void ngx_http_set_keepalive(ngx_h } c->tcp_nopush = NGX_TCP_NOPUSH_UNSET; + tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0; } else { - if (clcf->tcp_nodelay && !c->tcp_nodelay) { - tcp_nodelay = 1; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); - - if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, - (const void *) &tcp_nodelay, sizeof(int)) == -1) - { - ngx_connection_error(c, ngx_socket_errno, - "setsockopt(TCP_NODELAY) failed"); - ngx_http_close_connection(c); - return; - } - - c->tcp_nodelay = 1; + tcp_nodelay = 1; + } + + if (tcp_nodelay && clcf->tcp_nodelay && !c->tcp_nodelay) { + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); + + if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) == -1) + { + ngx_connection_error(c, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + ngx_http_close_connection(c); + return; } + + c->tcp_nodelay = 1; } #if 0 @@ -1761,6 +1764,11 @@ static void ngx_http_keepalive_handler(n ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno, "kevent() reported that client %V closed " "keepalive connection", ctx->client); +#if (NGX_HTTP_SSL) + if (c->ssl) { + c->ssl->no_send_shut = 1; + } +#endif ngx_http_close_connection(c); return; } diff --git a/src/http/ngx_http_write_filter.c b/src/http/ngx_http_write_filter.c --- a/src/http/ngx_http_write_filter.c +++ b/src/http/ngx_http_write_filter.c @@ -152,8 +152,7 @@ ngx_int_t ngx_http_write_filter(ngx_http sent = c->sent; - chain = c->send_chain(c, ctx->out, - clcf->limit_rate ? clcf->limit_rate: OFF_T_MAX_VALUE); + chain = c->send_chain(c, ctx->out, clcf->limit_rate); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http write filter %p", chain); diff --git a/src/os/unix/ngx_aio_write_chain.c b/src/os/unix/ngx_aio_write_chain.c --- a/src/os/unix/ngx_aio_write_chain.c +++ b/src/os/unix/ngx_aio_write_chain.c @@ -20,6 +20,12 @@ ngx_chain_t *ngx_aio_write_chain(ngx_con ngx_err_t err; ngx_chain_t *cl; + /* the maximum limit size is the maximum size_t value - the page size */ + + if (limit == 0 || limit > MAX_SIZE_T_VALUE - ngx_pagesize) { + limit = MAX_SIZE_T_VALUE - ngx_pagesize; + } + send = 0; sent = 0; cl = in; 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 @@ -104,7 +104,7 @@ ngx_int_t ngx_open_dir(ngx_str_t *name, #else #define ngx_de_namelen(dir) ngx_strlen((dir)->de->d_name) #endif -#define ngx_de_info(name, dir) stat((const char *) name, &(dir)->info) +#define ngx_de_info(name, dir) lstat((const char *) name, &(dir)->info) #define ngx_de_info_n "stat()" #define ngx_de_is_dir(dir) (S_ISDIR((dir)->info.st_mode)) #define ngx_de_is_file(dir) (S_ISREG((dir)->info.st_mode)) diff --git a/src/os/unix/ngx_freebsd_init.c b/src/os/unix/ngx_freebsd_init.c --- a/src/os/unix/ngx_freebsd_init.c +++ b/src/os/unix/ngx_freebsd_init.c @@ -204,6 +204,9 @@ ngx_int_t ngx_os_init(ngx_log_t *log) } + ngx_tcp_nodelay_and_tcp_nopush = 1; + + return ngx_posix_init(log); } 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 @@ -37,9 +37,8 @@ ngx_chain_t *ngx_freebsd_sendfile_chain( { int rc; u_char *prev; - off_t fprev, sent, send, sprev, aligned; - size_t hsize, fsize; - ssize_t size; + off_t size, send, prev_send, aligned, sent, fprev; + size_t header_size, file_size; ngx_uint_t eintr, eagain, complete; ngx_err_t err; ngx_buf_t *file; @@ -67,6 +66,12 @@ ngx_chain_t *ngx_freebsd_sendfile_chain( #endif + /* the maximum limit size is the maximum size_t value - the page size */ + + if (limit == 0 || limit > MAX_SIZE_T_VALUE - ngx_pagesize) { + limit = MAX_SIZE_T_VALUE - ngx_pagesize; + } + send = 0; eagain = 0; @@ -82,11 +87,11 @@ ngx_chain_t *ngx_freebsd_sendfile_chain( for ( ;; ) { file = NULL; - fsize = 0; - hsize = 0; + file_size = 0; + header_size = 0; eintr = 0; complete = 0; - sprev = send; + prev_send = send; header.nelts = 0; trailer.nelts = 0; @@ -115,7 +120,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain( } if (prev == cl->buf->pos) { - iov->iov_len += size; + iov->iov_len += (size_t) size; } else { if (!(iov = ngx_array_push(&header))) { @@ -123,11 +128,11 @@ ngx_chain_t *ngx_freebsd_sendfile_chain( } iov->iov_base = (void *) cl->buf->pos; - iov->iov_len = size; + iov->iov_len = (size_t) size; } - prev = cl->buf->pos + size; - hsize += size; + prev = cl->buf->pos + (size_t) size; + header_size += (size_t) size; send += size; } @@ -138,7 +143,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain( /* coalesce the neighbouring file bufs */ do { - size = (size_t) (cl->buf->file_last - cl->buf->file_pos); + size = cl->buf->file_last - cl->buf->file_pos; if (send + size > limit) { size = limit - send; @@ -151,7 +156,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain( } } - fsize += size; + file_size += (size_t) size; send += size; fprev = cl->buf->file_pos + size; cl = cl->next; @@ -189,7 +194,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain( } if (prev == cl->buf->pos) { - iov->iov_len += size; + iov->iov_len += (size_t) size; } else { if (!(iov = ngx_array_push(&trailer))) { @@ -197,10 +202,10 @@ ngx_chain_t *ngx_freebsd_sendfile_chain( } iov->iov_base = (void *) cl->buf->pos; - iov->iov_len = size; + iov->iov_len = (size_t) size; } - prev = cl->buf->pos + size; + prev = cl->buf->pos + (size_t) size; send += size; cl = cl->next; } @@ -245,13 +250,13 @@ ngx_chain_t *ngx_freebsd_sendfile_chain( */ if (ngx_freebsd_sendfile_nbytes_bug == 0) { - hsize = 0; + header_size = 0; } sent = 0; rc = sendfile(file->file->fd, c->fd, file->file_pos, - fsize + hsize, &hdtr, &sent, 0); + file_size + header_size, &hdtr, &sent, 0); if (rc == -1) { err = ngx_errno; @@ -265,8 +270,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain( } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err, - "sendfile() sent only %O bytes", - sent); + "sendfile() sent only %O bytes", sent); } else { wev->error = 1; @@ -291,13 +295,13 @@ ngx_chain_t *ngx_freebsd_sendfile_chain( ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, "sendfile: %d, @%O %O:%uz", - rc, file->file_pos, sent, fsize + hsize); + rc, file->file_pos, sent, file_size + header_size); } else { rc = writev(c->fd, header.elts, header.nelts); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, - "writev: %d of %uz", rc, hsize); + "writev: %d of %uz", rc, header_size); if (rc == -1) { err = ngx_errno; @@ -320,7 +324,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain( sent = rc > 0 ? rc : 0; } - if (send - sprev == sent) { + if (send - prev_send == sent) { complete = 1; } @@ -353,7 +357,7 @@ ngx_chain_t *ngx_freebsd_sendfile_chain( } if (ngx_buf_in_memory(cl->buf)) { - cl->buf->pos += sent; + cl->buf->pos += (size_t) sent; } if (cl->buf->in_file) { diff --git a/src/os/unix/ngx_linux_sendfile_chain.c b/src/os/unix/ngx_linux_sendfile_chain.c --- a/src/os/unix/ngx_linux_sendfile_chain.c +++ b/src/os/unix/ngx_linux_sendfile_chain.c @@ -25,11 +25,10 @@ ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) { - int rc; + int rc, tcp_nodelay; u_char *prev; - off_t fprev, send, sprev, aligned; - size_t fsize; - ssize_t size, sent; + off_t size, send, prev_send, aligned, sent, fprev; + size_t file_size; ngx_uint_t eintr, complete; ngx_err_t err; ngx_buf_t *file; @@ -49,6 +48,14 @@ ngx_chain_t *ngx_linux_sendfile_chain(ng return in; } + + /* the maximum limit size is the maximum size_t value - the page size */ + + if (limit == 0 || limit > MAX_SIZE_T_VALUE - ngx_pagesize) { + limit = MAX_SIZE_T_VALUE - ngx_pagesize; + } + + send = 0; header.elts = headers; @@ -58,10 +65,10 @@ ngx_chain_t *ngx_linux_sendfile_chain(ng for ( ;; ) { file = NULL; - fsize = 0; + file_size = 0; eintr = 0; complete = 0; - sprev = send; + prev_send = send; header.nelts = 0; @@ -89,7 +96,7 @@ ngx_chain_t *ngx_linux_sendfile_chain(ng } if (prev == cl->buf->pos) { - iov->iov_len += size; + iov->iov_len += (size_t) size; } else { if (!(iov = ngx_array_push(&header))) { @@ -97,10 +104,10 @@ ngx_chain_t *ngx_linux_sendfile_chain(ng } iov->iov_base = (void *) cl->buf->pos; - iov->iov_len = size; + iov->iov_len = (size_t) size; } - prev = cl->buf->pos + size; + prev = cl->buf->pos + (size_t) size; send += size; } @@ -111,25 +118,62 @@ ngx_chain_t *ngx_linux_sendfile_chain(ng && cl && cl->buf->in_file) { - if (ngx_tcp_nopush(c->fd) == NGX_ERROR) { - err = ngx_errno; + + /* the TCP_CORK and TCP_NODELAY are mutually exclusive */ + + if (c->tcp_nodelay) { + + tcp_nodelay = 0; + + if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) == -1) + { + err = ngx_errno; - /* - * there is a tiny chance to be interrupted, however - * we continue a processing without the TCP_CORK - */ + /* + * there is a tiny chance to be interrupted, however + * we continue a processing with the TCP_NODELAY + * and without the TCP_CORK + */ + + if (err != NGX_EINTR) { + wev->error = 1; + ngx_connection_error(c, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + return NGX_CHAIN_ERROR; + } + + } else { + c->tcp_nodelay = 0; - if (err != NGX_EINTR) { - wev->error = 1; - ngx_connection_error(c, err, ngx_tcp_nopush_n " failed"); - return NGX_CHAIN_ERROR; + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, + "no tcp_nodelay"); } + } + + if (!c->tcp_nodelay) { + + if (ngx_tcp_nopush(c->fd) == NGX_ERROR) { + err = ngx_errno; - } else { - c->tcp_nopush = NGX_TCP_NOPUSH_SET; + /* + * there is a tiny chance to be interrupted, however + * we continue a processing without the TCP_CORK + */ - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, - "tcp_nopush"); + if (err != NGX_EINTR) { + wev->error = 1; + ngx_connection_error(c, err, + ngx_tcp_nopush_n " failed"); + return NGX_CHAIN_ERROR; + } + + } else { + c->tcp_nopush = NGX_TCP_NOPUSH_SET; + + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, + "tcp_nopush"); + } } } @@ -141,7 +185,7 @@ ngx_chain_t *ngx_linux_sendfile_chain(ng /* coalesce the neighbouring file bufs */ do { - size = (size_t) (cl->buf->file_last - cl->buf->file_pos); + size = cl->buf->file_last - cl->buf->file_pos; if (send + size > limit) { size = limit - send; @@ -154,7 +198,7 @@ ngx_chain_t *ngx_linux_sendfile_chain(ng } } - fsize += size; + file_size += (size_t) size; send += size; fprev = cl->buf->file_pos + size; cl = cl->next; @@ -172,7 +216,7 @@ ngx_chain_t *ngx_linux_sendfile_chain(ng #else offset = (int32_t) file->file_pos; #endif - rc = sendfile(c->fd, file->file->fd, &offset, fsize); + rc = sendfile(c->fd, file->file->fd, &offset, file_size); if (rc == -1) { err = ngx_errno; @@ -195,8 +239,8 @@ ngx_chain_t *ngx_linux_sendfile_chain(ng sent = rc > 0 ? rc : 0; ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, - "sendfile: %d, @%O %z:%uz", - rc, file->file_pos, sent, fsize); + "sendfile: %d, @%O %O:%uz", + rc, file->file_pos, sent, file_size); } else { rc = writev(c->fd, header.elts, header.nelts); @@ -221,10 +265,10 @@ ngx_chain_t *ngx_linux_sendfile_chain(ng sent = rc > 0 ? rc : 0; - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %z", sent); + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %O", sent); } - if (send - sprev == sent) { + if (send - prev_send == sent) { complete = 1; } @@ -257,7 +301,7 @@ ngx_chain_t *ngx_linux_sendfile_chain(ng } if (ngx_buf_in_memory(cl->buf)) { - cl->buf->pos += sent; + cl->buf->pos += (size_t) sent; } if (cl->buf->in_file) { diff --git a/src/os/unix/ngx_os.h b/src/os/unix/ngx_os.h --- a/src/os/unix/ngx_os.h +++ b/src/os/unix/ngx_os.h @@ -50,7 +50,8 @@ ngx_chain_t *ngx_writev_chain(ngx_connec extern ngx_os_io_t ngx_os_io; extern ngx_int_t ngx_ncpu; extern ngx_int_t ngx_max_sockets; -extern ngx_int_t ngx_inherited_nonblocking; +extern ngx_uint_t ngx_inherited_nonblocking; +extern ngx_uint_t ngx_tcp_nodelay_and_tcp_nopush; #define ngx_stderr_fileno STDERR_FILENO diff --git a/src/os/unix/ngx_posix_init.c b/src/os/unix/ngx_posix_init.c --- a/src/os/unix/ngx_posix_init.c +++ b/src/os/unix/ngx_posix_init.c @@ -8,9 +8,10 @@ #include -ngx_int_t ngx_ncpu; -ngx_int_t ngx_max_sockets; -ngx_int_t ngx_inherited_nonblocking; +ngx_int_t ngx_ncpu; +ngx_int_t ngx_max_sockets; +ngx_uint_t ngx_inherited_nonblocking; +ngx_uint_t ngx_tcp_nodelay_and_tcp_nopush; struct rlimit rlmt; diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -17,7 +17,7 @@ static void ngx_signal_worker_processes( static ngx_uint_t ngx_reap_childs(ngx_cycle_t *cycle); static void ngx_master_exit(ngx_cycle_t *cycle); static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data); -static void ngx_worker_process_init(ngx_cycle_t *cycle); +static void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_uint_t priority); static void ngx_channel_handler(ngx_event_t *ev); #if (NGX_THREADS) static void ngx_wakeup_worker_threads(ngx_cycle_t *cycle); @@ -564,6 +564,33 @@ static ngx_uint_t ngx_reap_childs(ngx_cy continue; } + + ch.command = NGX_CMD_OPEN_CHANNEL; + ch.pid = ngx_processes[ngx_process_slot].pid; + ch.slot = ngx_process_slot; + ch.fd = ngx_processes[ngx_process_slot].channel[0]; + + for (n = 0; n < ngx_last_process; n++) { + + if (n == ngx_process_slot + || ngx_processes[n].pid == -1 + || ngx_processes[n].channel[0] == -1) + { + continue; + } + + ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0, + "pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d", + ch.slot, ch.pid, ch.fd, + n, ngx_processes[n].pid, + ngx_processes[n].channel[0]); + + /* TODO: NGX_AGAIN */ + + ngx_write_channel(ngx_processes[n].channel[0], + &ch, sizeof(ngx_channel_t), cycle->log); + } + live = 1; continue; @@ -611,7 +638,7 @@ static void ngx_worker_process_cycle(ngx ngx_err_t err; ngx_core_conf_t *ccf; - ngx_worker_process_init(cycle); + ngx_worker_process_init(cycle, 1); ngx_setproctitle("worker process"); @@ -718,7 +745,7 @@ static void ngx_worker_process_cycle(ngx } -static void ngx_worker_process_init(ngx_cycle_t *cycle) +static void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_uint_t priority) { sigset_t set; ngx_int_t n; @@ -739,6 +766,13 @@ static void ngx_worker_process_init(ngx_ ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (geteuid() == 0) { + if (priority && ccf->priority != 0) { + if (setpriority(PRIO_PROCESS, 0, ccf->priority) == -1) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, + "setpriority(%d) failed", ccf->priority); + } + } + if (setgid(ccf->group) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "setgid(%d) failed", ccf->group); @@ -746,6 +780,12 @@ static void ngx_worker_process_init(ngx_ exit(2); } + if (initgroups(ccf->username, ccf->group) == -1) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, + "initgroups(%s, %d) failed", + ccf->username, ccf->group); + } + if (setuid(ccf->user) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "setuid(%d) failed", ccf->user); @@ -1041,7 +1081,7 @@ static void ngx_garbage_collector_cycle( ngx_path_t **path; ngx_event_t *ev; - ngx_worker_process_init(cycle); + ngx_worker_process_init(cycle, 0); ev = &cycle->read_events[ngx_channel]; diff --git a/src/os/unix/ngx_solaris_sendfilev_chain.c b/src/os/unix/ngx_solaris_sendfilev_chain.c --- a/src/os/unix/ngx_solaris_sendfilev_chain.c +++ b/src/os/unix/ngx_solaris_sendfilev_chain.c @@ -9,6 +9,28 @@ #include +#if (NGX_TEST_BUILD_SOLARIS_SENDFILEV) + +/* Solaris declarations */ + +typedef struct sendfilevec { + int sfv_fd; + u_int sfv_flag; + off_t sfv_off; + size_t sfv_len; +} sendfilevec_t; + +#define SFV_FD_SELF -2 + +static ssize_t sendfilev(int fd, const struct sendfilevec *vec, + int sfvcnt, size_t *xferred) +{ + return -1; +} + +#endif + + #define NGX_SENDFILEVECS 16 @@ -17,8 +39,9 @@ ngx_chain_t *ngx_solaris_sendfilev_chain { int fd; u_char *prev; - off_t fprev, sprev, send, aligned; - ssize_t size, sent, n; + off_t size, send, prev_send, aligned, fprev; + size_t sent; + ssize_t n; ngx_int_t eintr, complete; ngx_err_t err; sendfilevec_t *sfv, sfvs[NGX_SENDFILEVECS]; @@ -36,6 +59,14 @@ ngx_chain_t *ngx_solaris_sendfilev_chain return ngx_writev_chain(c, in, limit); } + + /* the maximum limit size is the maximum size_t value - the page size */ + + if (limit == 0 || limit > MAX_SIZE_T_VALUE - ngx_pagesize) { + limit = MAX_SIZE_T_VALUE - ngx_pagesize; + } + + send = 0; complete = 0; @@ -51,7 +82,7 @@ ngx_chain_t *ngx_solaris_sendfilev_chain sfv = NULL; eintr = 0; sent = 0; - sprev = send; + prev_send = send; vec.nelts = 0; @@ -73,7 +104,7 @@ ngx_chain_t *ngx_solaris_sendfilev_chain } if (prev == cl->buf->pos) { - sfv->sfv_len += size; + sfv->sfv_len += (size_t) size; } else { if (!(sfv = ngx_array_push(&vec))) { @@ -83,16 +114,16 @@ ngx_chain_t *ngx_solaris_sendfilev_chain sfv->sfv_fd = SFV_FD_SELF; sfv->sfv_flag = 0; sfv->sfv_off = (off_t) (uintptr_t) cl->buf->pos; - sfv->sfv_len = size; + sfv->sfv_len = (size_t) size; } - prev = cl->buf->pos + size; + prev = cl->buf->pos + (size_t) size; send += size; } else { prev = NULL; - size = (size_t) (cl->buf->file_last - cl->buf->file_pos); + size = cl->buf->file_last - cl->buf->file_pos; if (send + size > limit) { size = limit - send; @@ -106,7 +137,7 @@ ngx_chain_t *ngx_solaris_sendfilev_chain } if (fd == cl->buf->file->fd && fprev == cl->buf->file_pos) { - sfv->sfv_len += size; + sfv->sfv_len += (size_t) size; } else { if (!(sfv = ngx_array_push(&vec))) { @@ -117,7 +148,7 @@ ngx_chain_t *ngx_solaris_sendfilev_chain sfv->sfv_fd = fd; sfv->sfv_flag = 0; sfv->sfv_off = cl->buf->file_pos; - sfv->sfv_len = size; + sfv->sfv_len = (size_t) size; } fprev = cl->buf->file_pos + size; @@ -136,7 +167,7 @@ ngx_chain_t *ngx_solaris_sendfilev_chain } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err, - "sendfilev() sent only %z bytes", sent); + "sendfilev() sent only %uz bytes", sent); } else { wev->error = 1; @@ -148,7 +179,7 @@ ngx_chain_t *ngx_solaris_sendfilev_chain ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "sendfilev: %z %z", n, sent); - if (send - sprev == sent) { + if (send - prev_send == (off_t) sent) { complete = 1; } @@ -166,8 +197,8 @@ ngx_chain_t *ngx_solaris_sendfilev_chain size = ngx_buf_size(cl->buf); - if (sent >= size) { - sent -= size; + if ((off_t) sent >= size) { + sent = (size_t) ((off_t) sent - size); if (ngx_buf_in_memory(cl->buf)) { cl->buf->pos = cl->buf->last; 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 @@ -16,7 +16,7 @@ ngx_chain_t *ngx_writev_chain(ngx_connec { u_char *prev; ssize_t n, size, sent; - off_t send, sprev; + off_t send, prev_send; ngx_uint_t eintr, complete; ngx_err_t err; ngx_array_t vec; @@ -42,6 +42,12 @@ ngx_chain_t *ngx_writev_chain(ngx_connec #endif + /* the maximum limit size is the maximum size_t value - the page size */ + + if (limit == 0 || limit > MAX_SIZE_T_VALUE - ngx_pagesize) { + limit = MAX_SIZE_T_VALUE - ngx_pagesize; + } + send = 0; complete = 0; @@ -54,7 +60,7 @@ ngx_chain_t *ngx_writev_chain(ngx_connec prev = NULL; iov = NULL; eintr = 0; - sprev = send; + prev_send = send; vec.nelts = 0; @@ -118,7 +124,7 @@ ngx_chain_t *ngx_writev_chain(ngx_connec ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %z", sent); - if (send - sprev == sent) { + if (send - prev_send == sent) { complete = 1; }