# HG changeset patch # User Igor Sysoev # Date 1169672400 -10800 # Node ID 704622b2528a3ba47f2fdb0ef2ed8736a1eedecc # Parent b3aec7787b8e80389796de33666b9bb4ef64cf3f nginx 0.5.9 *) Change: now the ngx_http_memcached_module uses the $memcached_key variable value as a key. *) Feature: the $memcached_key variable. *) Feature: the "clean" parameter in the "client_body_in_file_only" directive. *) Feature: the "env" directive. *) Feature: the "sendfile" directive is available inside the "if" block. *) Feature: now on failure of the writing to access nginx logs a message to error_log, but not more often than once a minute. *) Bugfix: the "access_log off" directive did not always turn off the logging. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,25 @@ +Changes with nginx 0.5.9 25 Jan 2007 + + *) Change: now the ngx_http_memcached_module uses the $memcached_key + variable value as a key. + + *) Feature: the $memcached_key variable. + + *) Feature: the "clean" parameter in the "client_body_in_file_only" + directive. + + *) Feature: the "env" directive. + + *) Feature: the "sendfile" directive is available inside the "if" block. + + *) Feature: now on failure of the writing to access nginx logs a + message to error_log, but not more often than once a minute. + + *) Bugfix: the "access_log off" directive did not always turn off the + logging. + + Changes with nginx 0.5.8 19 Jan 2007 *) Bugfix: a segmentation fault might occur if @@ -737,7 +758,7 @@ Changes with nginx 0.3.38 *) Feature: the "client_body_in_file_only" directive. - *) Workaround: no on disk overflow nginx tries to write access logs + *) Workaround: now on disk overflow nginx tries to write access logs once a second only. Thanks to Anton Yuzhaninov and Maxim Dounin. @@ -834,7 +855,7 @@ Changes with nginx 0.3.31 *) Workaround: for MacOSX 64-bit kernel kqueue millisecond timeout bug. - Thanks Andrei Nigmatulin. + Thanks to Andrei Nigmatulin. *) Bugfix: if there were several "listen" directives listening one various addresses inside one server, then server names like diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,24 @@ +Изменения в nginx 0.5.9 25.01.2007 + + *) Изменение: модуль ngx_http_memcached_module теперь в качестве ключа + использует значение переменной $memcached_key. + + *) Добавление: переменная $memcached_key. + + *) Добавление: параметр clean в директиве client_body_in_file_only. + + *) Добавление: директива env. + + *) Добавление: директива sendfile работает внутри блока if. + + *) Добавление: теперь при ошибке записи в access_log nginx записывает + сообщение в error_log, но не чаще одного раза в минуту. + + *) Исправление: директива "access_log off" не всегда запрещала запись в + лог. + + Изменения в nginx 0.5.8 19.01.2007 *) Исправление: если использовалась директива @@ -11,8 +31,9 @@ делался переход к следующему бэкенду. *) Исправление: если при использовании директивы "proxy_buffering off" - соединение с клиентом было неактивно, то оно закрывалось по таймуту, - заданному директивой send_timeout; ошибка появилась в 0.4.7. + соединение с клиентом было неактивно, то оно закрывалось по + таймауту, заданному директивой send_timeout; ошибка появилась в + 0.4.7. *) Исправление: если при использовании метода epoll клиент закрывал преждевременно соединение со своей стороны, то nginx закрывал это 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_env(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 char *ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -128,6 +129,13 @@ static ngx_command_t ngx_core_commands[ offsetof(ngx_core_conf_t, working_directory), NULL }, + { ngx_string("env"), + NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, + ngx_set_env, + 0, + 0, + NULL }, + #if (NGX_THREADS) { ngx_string("worker_threads"), @@ -178,7 +186,7 @@ ngx_uint_t ngx_max_module; static ngx_uint_t ngx_show_version; static ngx_uint_t ngx_show_configure; -static char *ngx_null_environ = NULL; +static char **ngx_os_environ; int ngx_cdecl @@ -275,8 +283,6 @@ main(int argc, char *const *argv) return 1; } - environ = &ngx_null_environ; - ngx_max_module = 0; for (i = 0; ngx_modules[i]; i++) { ngx_modules[i]->index = ngx_max_module++; @@ -407,21 +413,128 @@ ngx_add_inherited_sockets(ngx_cycle_t *c } +char ** +ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last) +{ + char **p, **env; + ngx_str_t *var; + ngx_uint_t i, n; + ngx_core_conf_t *ccf; + + ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); + + if (last) { + n = *last; + + } else { + if (ccf->environment) { + return ccf->environment; + } + + n = 0; + } + + var = ccf->env.elts; + + for (i = 0; i < ccf->env.nelts; i++) { + if (ngx_strcmp(var[i].data, "TZ") == 0 + || ngx_strncmp(var[i].data, "TZ=", 3) == 0) + { + goto tz_found; + } + } + + var = ngx_array_push(&ccf->env); + + var->len = 2; + var->data = (u_char *) "TZ"; + + var = ccf->env.elts; + +tz_found: + + for (i = 0; i < ccf->env.nelts; i++) { + + if (var[i].data[var[i].len] == '=') { + n++; + continue; + } + + for (p = ngx_os_environ; *p; p++) { + + if (ngx_strncmp(*p, var[i].data, var[i].len) == 0 + && (*p)[var[i].len] == '=') + { + n++; + break; + } + } + } + + if (last) { + *last = n; + env = ngx_alloc((n + 1) * sizeof(char *), cycle->log); + + } else { + env = ngx_palloc(cycle->pool, (n + 1) * sizeof(char *)); + } + + if (env == NULL) { + return NULL; + } + + n = 0; + + for (i = 0; i < ccf->env.nelts; i++) { + + if (var[i].data[var[i].len] == '=') { + env[n++] = (char *) var[i].data; + continue; + } + + for (p = ngx_os_environ; *p; p++) { + + if (ngx_strncmp(*p, var[i].data, var[i].len) == 0 + && (*p)[var[i].len] == '=') + { + env[n++] = *p; + break; + } + } + } + + env[n] = NULL; + + if (last == NULL) { + ccf->environment = env; + environ = env; + } + + return env; +} + + ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv) { - char *env[3], *var; - u_char *p; - ngx_uint_t i; - ngx_pid_t pid; - ngx_exec_ctx_t ctx; - ngx_core_conf_t *ccf; - ngx_listening_t *ls; + char **env, *var; + u_char *p; + ngx_uint_t i, n; + ngx_pid_t pid; + ngx_exec_ctx_t ctx; + ngx_core_conf_t *ccf; + ngx_listening_t *ls; ctx.path = argv[0]; ctx.name = "new binary process"; ctx.argv = argv; + n = 2; + env = ngx_set_environment(cycle, &n); + if (env == NULL) { + return NGX_INVALID_PID; + } + var = ngx_alloc(sizeof(NGINX_VAR) + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 2, cycle->log); @@ -435,40 +548,42 @@ ngx_exec_new_binary(ngx_cycle_t *cycle, *p = '\0'; - ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, "inherited: %s", var); - - env[0] = var; + env[n++] = var; #if (NGX_SETPROCTITLE_USES_ENV) /* allocate the spare 300 bytes for the new binary process title */ - env[1] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" - "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; - - env[2] = NULL; - -#else - - env[1] = NULL; + env[n++] = "SPARE=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; #endif - ctx.envp = (char *const *) &env; + env[n] = NULL; + +#if (NGX_DEBUG) + { + char **e; + for (e = env; *e; e++) { + ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, "env: %s", *e); + } + } +#endif + + ctx.envp = (char *const *) env; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); - if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data) - != NGX_OK) - { + if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data) != NGX_OK) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_rename_file_n " %s to %s failed " "before executing new binary process \"%s\"", ccf->pid.data, ccf->oldpid.data, argv[0]); + ngx_free(env); ngx_free(var); return NGX_INVALID_PID; @@ -477,16 +592,15 @@ ngx_exec_new_binary(ngx_cycle_t *cycle, pid = ngx_execute(cycle, &ctx); if (pid == NGX_INVALID_PID) { - if (ngx_rename_file(ccf->oldpid.data, ccf->pid.data) - != NGX_OK) - { + if (ngx_rename_file(ccf->oldpid.data, ccf->pid.data) != NGX_OK) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, - ngx_rename_file_n " %s back to %s failed " - "after try to executing new binary process \"%s\"", + ngx_rename_file_n " %s back to %s failed after " + "the try to execute the new binary process \"%s\"", ccf->oldpid.data, ccf->pid.data, argv[0]); } } + ngx_free(env); ngx_free(var); return pid; @@ -588,6 +702,8 @@ ngx_save_argv(ngx_cycle_t *cycle, int ar #endif + ngx_os_environ = environ; + return NGX_OK; } @@ -631,6 +747,12 @@ ngx_core_module_create_conf(ngx_cycle_t ccf->thread_stack_size = NGX_CONF_UNSET_SIZE; #endif + if (ngx_array_init(&ccf->env, cycle->pool, 1, sizeof(ngx_str_t)) + != NGX_OK) + { + return NULL; + } + return ccf; } @@ -641,9 +763,9 @@ ngx_core_module_init_conf(ngx_cycle_t *c ngx_core_conf_t *ccf = conf; #if !(NGX_WIN32) - ngx_str_t lock_file; - struct passwd *pwd; - struct group *grp; + ngx_str_t lock_file; + struct group *grp; + struct passwd *pwd; #endif ngx_conf_init_value(ccf->daemon, 1); @@ -830,6 +952,36 @@ ngx_set_user(ngx_conf_t *cf, ngx_command static char * +ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_core_conf_t *ccf = conf; + + ngx_str_t *value, *var; + ngx_uint_t i; + + var = ngx_array_push(&ccf->env); + if (var == NULL) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + *var = value[1]; + + for (i = 0; i < value[1].len; i++) { + + if (value[1].data[i] == '=') { + + var->len = i; + + return NGX_CONF_OK; + } + } + + return NGX_CONF_OK; +} + + +static char * ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_core_conf_t *ccf = conf; 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.8" +#define NGINX_VERSION "0.5.9" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" 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 @@ -93,6 +93,9 @@ typedef struct { ngx_str_t pid; ngx_str_t oldpid; + ngx_array_t env; + char **environment; + #if (NGX_THREADS) ngx_int_t worker_threads; size_t thread_stack_size; @@ -113,6 +116,7 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t ngx_int_t ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log); void ngx_delete_pidfile(ngx_cycle_t *cycle); void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user); +char **ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last); ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv); u_long ngx_get_cpu_affinity(ngx_uint_t n); ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, 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->access); + tf->persistent, tf->clean, 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 access) + ngx_uint_t persistent, ngx_uint_t clean, ngx_uint_t access) { ngx_err_t err; ngx_atomic_uint_t n; @@ -79,7 +79,7 @@ ngx_create_temp_file(ngx_file_t *file, n if (file->fd != NGX_INVALID_FILE) { - cln->handler = ngx_pool_cleanup_file; + cln->handler = clean ? ngx_pool_delete_file : ngx_pool_cleanup_file; clnf = cln->data; clnf->fd = file->fd; 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 @@ -53,6 +53,7 @@ typedef struct { unsigned log_level:8; unsigned persistent:1; + unsigned clean:1; } ngx_temp_file_t; @@ -81,7 +82,8 @@ struct ngx_tree_ctx_s { 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 access); + ngx_pool_t *pool, ngx_uint_t persistent, ngx_uint_t clean, + 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_palloc.c b/src/core/ngx_palloc.c --- a/src/core/ngx_palloc.c +++ b/src/core/ngx_palloc.c @@ -243,6 +243,32 @@ ngx_pool_cleanup_file(void *data) } +void +ngx_pool_delete_file(void *data) +{ + ngx_pool_cleanup_file_t *c = data; + + ngx_err_t err; + + ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, c->log, 0, "run cleanup: %p, fd:%d %s", + c, c->fd, c->name); + + if (ngx_delete_file(c->name) == NGX_FILE_ERROR) { + err = ngx_errno; + + if (err != NGX_ENOENT) { + ngx_log_error(NGX_LOG_CRIT, c->log, err, + ngx_delete_file_n " \"%s\" failed", c->name); + } + } + + if (ngx_close_file(c->fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, + ngx_close_file_n " \"%s\" failed", c->name); + } +} + + #if 0 static void * diff --git a/src/core/ngx_palloc.h b/src/core/ngx_palloc.h --- a/src/core/ngx_palloc.h +++ b/src/core/ngx_palloc.h @@ -60,7 +60,6 @@ typedef struct { } ngx_pool_cleanup_file_t; - void *ngx_alloc(size_t size, ngx_log_t *log); void *ngx_calloc(size_t size, ngx_log_t *log); @@ -74,6 +73,7 @@ ngx_int_t ngx_pfree(ngx_pool_t *pool, vo ngx_pool_cleanup_t *ngx_pool_cleanup_add(ngx_pool_t *p, size_t size); void ngx_pool_cleanup_file(void *data); +void ngx_pool_delete_file(void *data); #endif /* _NGX_PALLOC_H_INCLUDED_ */ 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 @@ -135,7 +135,7 @@ ngx_http_dav_handler(ngx_http_request_t r->request_body_in_file_only = 1; r->request_body_in_persistent_file = 1; - r->request_body_delete_incomplete_file = 1; + r->request_body_in_clean_file = 1; r->request_body_file_group_access = 1; r->request_body_file_log_level = 0; diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c --- a/src/http/modules/ngx_http_log_module.c +++ b/src/http/modules/ngx_http_log_module.c @@ -42,6 +42,7 @@ typedef struct { typedef struct { ngx_open_file_t *file; time_t disk_full_time; + time_t error_log_time; ngx_array_t *ops; /* array of ngx_http_log_op_t */ } ngx_http_log_t; @@ -59,6 +60,9 @@ typedef struct { } ngx_http_log_var_t; +static void ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, + u_char *buf, size_t len); + static u_char *ngx_http_log_connection(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op); static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf, @@ -151,7 +155,7 @@ ngx_module_t ngx_http_log_module = { }; -static ngx_str_t http_access_log = ngx_string(NGX_HTTP_LOG_PATH); +static ngx_str_t ngx_http_access_log = ngx_string(NGX_HTTP_LOG_PATH); static ngx_str_t ngx_http_combined_fmt = @@ -183,9 +187,9 @@ static ngx_http_log_var_t ngx_http_log_ ngx_int_t ngx_http_log_handler(ngx_http_request_t *r) { - ngx_uint_t i, l; u_char *line, *p; size_t len; + ngx_uint_t i, l; ngx_http_log_t *log; ngx_open_file_t *file; ngx_http_log_op_t *op; @@ -206,9 +210,9 @@ ngx_http_log_handler(ngx_http_request_t if (ngx_time() == log[l].disk_full_time) { /* - * On FreeBSD writing to a full filesystem with enabled softupdates + * on FreeBSD writing to a full filesystem with enabled softupdates * may block process for much longer time than writing to non-full - * filesystem, so we skip writing the log for one second. + * filesystem, so we skip writing to a log for one second */ continue; @@ -233,13 +237,8 @@ ngx_http_log_handler(ngx_http_request_t if (len > (size_t) (file->last - file->pos)) { - if (ngx_write_fd(file->fd, file->buffer, - file->pos - file->buffer) - == -1 - && ngx_errno == NGX_ENOSPC) - { - log[l].disk_full_time = ngx_time(); - } + ngx_http_log_write(r, &log[l], file->buffer, + file->pos - file->buffer); file->pos = file->buffer; } @@ -273,17 +272,57 @@ ngx_http_log_handler(ngx_http_request_t ngx_linefeed(p); - if (ngx_write_fd(file->fd, line, p - line) == -1 - && ngx_errno == NGX_ENOSPC) - { - log[l].disk_full_time = ngx_time(); - } + ngx_http_log_write(r, &log[l], line, p - line); } return NGX_OK; } +static void +ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, u_char *buf, + size_t len) +{ + time_t now; + ssize_t n; + ngx_err_t err; + + n = ngx_write_fd(log->file->fd, buf, len); + + if (n == (ssize_t) len) { + return; + } + + now = ngx_time(); + + if (n == -1) { + err = ngx_errno; + + if (err == NGX_ENOSPC) { + log->disk_full_time = now; + } + + if (now - log->error_log_time > 60) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, err, + ngx_write_fd_n " to \"%V\" failed", + &log->file->name); + + log->error_log_time = now; + } + + return; + } + + if (now - log->error_log_time > 60) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + ngx_write_fd_n " to \"%V\" was incomplete: %z of %uz", + &log->file->name, n, len); + + log->error_log_time = now; + } +} + + static u_char * ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op) @@ -515,47 +554,40 @@ ngx_http_log_merge_loc_conf(ngx_conf_t * ngx_http_log_fmt_t *fmt; ngx_http_log_main_conf_t *lmcf; - if (conf->logs == NULL) { + if (conf->logs || conf->off) { + return NGX_CONF_OK; + } - if (conf->off) { - return NGX_CONF_OK; - } - - if (prev->logs) { - conf->logs = prev->logs; + *conf = *prev; - } else { + if (conf->logs || conf->off) { + return NGX_CONF_OK; + } - if (prev->off) { - conf->off = prev->off; - return NGX_CONF_OK; - } - - conf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_http_log_t)); - if (conf->logs == NULL) { - return NGX_CONF_ERROR; - } + conf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_http_log_t)); + if (conf->logs == NULL) { + return NGX_CONF_ERROR; + } - log = ngx_array_push(conf->logs); - if (log == NULL) { - return NGX_CONF_ERROR; - } + log = ngx_array_push(conf->logs); + if (log == NULL) { + return NGX_CONF_ERROR; + } - log->file = ngx_conf_open_file(cf->cycle, &http_access_log); - if (log->file == NULL) { - return NGX_CONF_ERROR; - } + log->file = ngx_conf_open_file(cf->cycle, &ngx_http_access_log); + if (log->file == NULL) { + return NGX_CONF_ERROR; + } - log->disk_full_time = 0; - - lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module); - fmt = lmcf->formats.elts; + log->disk_full_time = 0; + log->error_log_time = 0; - /* the default "combined" format */ - log->ops = fmt[0].ops; - lmcf->combined_used = 1; - } - } + lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module); + fmt = lmcf->formats.elts; + + /* the default "combined" format */ + log->ops = fmt[0].ops; + lmcf->combined_used = 1; return NGX_CONF_OK; } @@ -600,6 +632,7 @@ ngx_http_log_set_log(ngx_conf_t *cf, ngx } log->disk_full_time = 0; + log->error_log_time = 0; if (cf->args->nelts >= 3) { name = value[2]; diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c --- a/src/http/modules/ngx_http_memcached_module.c +++ b/src/http/modules/ngx_http_memcached_module.c @@ -12,6 +12,7 @@ typedef struct { ngx_http_upstream_conf_t upstream; + ngx_int_t index; } ngx_http_memcached_loc_conf_t; @@ -147,6 +148,9 @@ ngx_module_t ngx_http_memcached_module }; +static ngx_str_t ngx_http_memcached_key = ngx_string("memcached_key"); + + #define NGX_HTTP_MEMCACHED_END (sizeof(ngx_http_memcached_end) - 1) static u_char ngx_http_memcached_end[] = CRLF "END" CRLF; @@ -221,14 +225,26 @@ ngx_http_memcached_handler(ngx_http_requ static ngx_int_t ngx_http_memcached_create_request(ngx_http_request_t *r) { - size_t len; - ngx_buf_t *b; - ngx_chain_t *cl; - ngx_http_memcached_ctx_t *ctx; + size_t len; + ngx_buf_t *b; + ngx_chain_t *cl; + ngx_http_memcached_ctx_t *ctx; + ngx_http_variable_value_t *vv; + ngx_http_memcached_loc_conf_t *mlcf; + + mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module); - len = sizeof("get ") - 1 + r->uri.len + sizeof(" " CRLF) - 1; - if (r->args.len) { - len += 1 + r->args.len; + vv = ngx_http_get_indexed_variable(r, mlcf->index); + + if (vv == NULL || vv->not_found || vv->len == 0) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "the \"$memcached_key\" variable is not set"); + return NGX_ERROR; + } + + len = sizeof("get ") - 1 + vv->len + sizeof(" " CRLF) - 1; + if (vv->len) { + len += 1 + vv->len; } b = ngx_create_temp_buf(r->pool, len); @@ -252,12 +268,7 @@ ngx_http_memcached_create_request(ngx_ht ctx->key.data = b->last; - b->last = ngx_copy(b->last, r->uri.data, r->uri.len); - - if (r->args.len) { - *b->last++ = '?'; - b->last = ngx_copy(b->last, r->args.data, r->args.len); - } + b->last = ngx_copy(b->last, vv->data, vv->len); ctx->key.len = b->last - ctx->key.data; @@ -504,7 +515,7 @@ ngx_http_memcached_create_loc_conf(ngx_c * conf->upstream.uri = { 0, NULL }; * conf->upstream.location = NULL; * - * conf->peers = NULL; + * conf->index = 0; */ conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC; @@ -604,6 +615,12 @@ ngx_http_memcached_pass(ngx_conf_t *cf, clcf->auto_redirect = 1; } + lcf->index = ngx_http_get_variable_index(cf, &ngx_http_memcached_key); + + if (lcf->index == NGX_ERROR) { + return NGX_CONF_ERROR; + } + return NGX_CONF_OK; } 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.8'; +our $VERSION = '0.5.9'; 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 @@ -363,7 +363,7 @@ has_request_body(r, next) r->request_body_in_single_buf = 1; r->request_body_in_persistent_file = 1; - r->request_body_delete_incomplete_file = 1; + r->request_body_in_clean_file = 1; if (r->request_body_in_file_only) { r->request_body_file_log_level = 0; diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c --- a/src/http/modules/perl/ngx_http_perl_module.c +++ b/src/http/modules/perl/ngx_http_perl_module.c @@ -44,9 +44,8 @@ static ngx_int_t ngx_http_perl_ssi(ngx_h static void ngx_http_perl_sleep_handler(ngx_http_request_t *r); static char *ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf); -static PerlInterpreter * - ngx_http_perl_create_interpreter(ngx_http_perl_main_conf_t *pmcf, - ngx_log_t *log); +static PerlInterpreter *ngx_http_perl_create_interpreter(ngx_conf_t *cf, + ngx_http_perl_main_conf_t *pmcf); static ngx_int_t ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires, ngx_log_t *log); static ngx_int_t ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r, @@ -475,7 +474,7 @@ ngx_http_perl_init_interpreter(ngx_conf_ PERL_SYS_INIT(&ngx_argc, &ngx_argv); - pmcf->perl = ngx_http_perl_create_interpreter(pmcf, cf->log); + pmcf->perl = ngx_http_perl_create_interpreter(cf, pmcf); if (pmcf->perl == NULL) { PERL_SYS_TERM(); @@ -500,8 +499,8 @@ ngx_http_perl_init_interpreter(ngx_conf_ static PerlInterpreter * -ngx_http_perl_create_interpreter(ngx_http_perl_main_conf_t *pmcf, - ngx_log_t *log) +ngx_http_perl_create_interpreter(ngx_conf_t *cf, + ngx_http_perl_main_conf_t *pmcf) { int n; STRLEN len; @@ -509,11 +508,15 @@ ngx_http_perl_create_interpreter(ngx_htt char *ver, *embedding[6]; PerlInterpreter *perl; - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "create perl interpreter"); + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0, "create perl interpreter"); + + if (ngx_set_environment(cf->cycle, NULL) == NULL) { + return NULL; + } perl = perl_alloc(); if (perl == NULL) { - ngx_log_error(NGX_LOG_ALERT, log, 0, "perl_alloc() failed"); + ngx_log_error(NGX_LOG_ALERT, cf->log, 0, "perl_alloc() failed"); return NULL; } @@ -546,7 +549,7 @@ ngx_http_perl_create_interpreter(ngx_htt n = perl_parse(perl, ngx_http_perl_xs_init, n, embedding, NULL); if (n != 0) { - ngx_log_error(NGX_LOG_ALERT, log, 0, "perl_parse() failed: %d", n); + ngx_log_error(NGX_LOG_ALERT, cf->log, 0, "perl_parse() failed: %d", n); goto fail; } @@ -554,13 +557,13 @@ ngx_http_perl_create_interpreter(ngx_htt ver = SvPV(sv, len); if (ngx_strcmp(ver, NGINX_VERSION) != 0) { - ngx_log_error(NGX_LOG_ALERT, log, 0, + ngx_log_error(NGX_LOG_ALERT, cf->log, 0, "version " NGINX_VERSION " of nginx.pm is required, " "but %s was found", ver); goto fail; } - if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, log) != NGX_OK) { + if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, cf->log) != NGX_OK) { goto fail; } 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 @@ -23,6 +23,11 @@ typedef struct { #define NGX_HTTP_LOCATION_REGEX 4 +#define NGX_HTTP_REQUEST_BODY_FILE_OFF 0 +#define NGX_HTTP_REQUEST_BODY_FILE_ON 1 +#define NGX_HTTP_REQUEST_BODY_FILE_CLEAN 2 + + static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r, ngx_array_t *locations, size_t len); @@ -74,6 +79,14 @@ static ngx_conf_deprecated_t ngx_conf_d }; +static ngx_conf_enum_t ngx_http_core_request_body_in_file[] = { + { ngx_string("off"), NGX_HTTP_REQUEST_BODY_FILE_OFF }, + { ngx_string("on"), NGX_HTTP_REQUEST_BODY_FILE_ON }, + { ngx_string("clean"), NGX_HTTP_REQUEST_BODY_FILE_CLEAN }, + { ngx_null_string, 0 } +}; + + static ngx_command_t ngx_http_core_commands[] = { { ngx_string("variables_hash_max_size"), @@ -269,13 +282,14 @@ static ngx_command_t ngx_http_core_comm { ngx_string("client_body_in_file_only"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, - ngx_conf_set_flag_slot, + ngx_conf_set_enum_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_core_loc_conf_t, client_body_in_file_only), - NULL }, + &ngx_http_core_request_body_in_file }, { ngx_string("sendfile"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF + |NGX_CONF_TAKE1, ngx_conf_set_flag_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_core_loc_conf_t, sendfile), @@ -876,6 +890,8 @@ ngx_http_update_location_config(ngx_http if (clcf->client_body_in_file_only) { r->request_body_in_file_only = 1; r->request_body_in_persistent_file = 1; + r->request_body_in_clean_file = + clcf->client_body_in_file_only == NGX_HTTP_REQUEST_BODY_FILE_CLEAN; r->request_body_file_log_level = NGX_LOG_NOTICE; } else { 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 @@ -409,7 +409,7 @@ struct ngx_http_request_s { unsigned request_body_in_single_buf:1; unsigned request_body_in_file_only:1; unsigned request_body_in_persistent_file:1; - unsigned request_body_delete_incomplete_file:1; + unsigned request_body_in_clean_file:1; unsigned request_body_file_group_access:1; unsigned request_body_file_log_level:3; 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 @@ -14,7 +14,6 @@ static void ngx_http_read_client_request static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r); static ngx_int_t ngx_http_write_request_body(ngx_http_request_t *r, ngx_chain_t *body); -static void ngx_http_finalize_request_body(ngx_http_request_t *r, ngx_int_t rc); static void ngx_http_read_discarded_body_handler(ngx_http_request_t *r); static ngx_int_t ngx_http_read_discarded_body(ngx_http_request_t *r); @@ -72,6 +71,7 @@ ngx_http_read_client_request_body(ngx_ht tf->warn = "a client request body is buffered to a temporary file"; tf->log_level = r->request_body_file_log_level; tf->persistent = r->request_body_in_persistent_file; + tf->clean = r->request_body_in_clean_file; if (r->request_body_file_group_access) { tf->access = 0660; @@ -80,7 +80,7 @@ ngx_http_read_client_request_body(ngx_ht rb->temp_file = tf; if (ngx_create_temp_file(&tf->file, tf->path, tf->pool, - tf->persistent, tf->access) + tf->persistent, tf->clean, tf->access) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; @@ -238,14 +238,14 @@ ngx_http_read_client_request_body_handle if (r->connection->read->timedout) { r->connection->timedout = 1; - ngx_http_finalize_request_body(r, NGX_HTTP_REQUEST_TIME_OUT); + ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT); return; } rc = ngx_http_do_read_client_request_body(r); if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { - ngx_http_finalize_request_body(r, rc); + ngx_http_finalize_request(r, rc); } } @@ -400,6 +400,7 @@ ngx_http_write_request_body(ngx_http_req tf->warn = "a client request body is buffered to a temporary file"; tf->log_level = r->request_body_file_log_level; tf->persistent = r->request_body_in_persistent_file; + tf->clean = r->request_body_in_clean_file; if (r->request_body_file_group_access) { tf->access = 0660; @@ -422,26 +423,6 @@ ngx_http_write_request_body(ngx_http_req } -static void -ngx_http_finalize_request_body(ngx_http_request_t *r, ngx_int_t rc) -{ - if (r->request_body->temp_file - && r->request_body_in_persistent_file - && r->request_body_delete_incomplete_file) - { - if (ngx_delete_file(r->request_body->temp_file->file.name.data) - == NGX_FILE_ERROR) - { - ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, - ngx_delete_file_n " \"%s\" failed", - r->request_body->temp_file->file.name.data); - } - } - - ngx_http_finalize_request(r, rc); -} - - ngx_int_t ngx_http_discard_body(ngx_http_request_t *r) { 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 @@ -757,15 +757,20 @@ ngx_worker_process_cycle(ngx_cycle_t *cy static void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_uint_t priority) { - sigset_t set; - ngx_int_t n; - ngx_uint_t i; - struct rlimit rlmt; - ngx_core_conf_t *ccf; - ngx_listening_t *ls; + sigset_t set; + ngx_int_t n; + ngx_uint_t i; + struct rlimit rlmt; + ngx_core_conf_t *ccf; + ngx_listening_t *ls; ngx_process = NGX_PROCESS_WORKER; + if (ngx_set_environment(cycle, NULL) == NULL) { + /* fatal */ + exit(2); + } + ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (geteuid() == 0) {