nginx-0.2.0-RELEASE import
*) The pid-file names used during online upgrade was changed and now is
not required a manual rename operation. The old master process adds
the ".oldbin" suffix to its pid-file and executes a new binary file.
The new master process creates usual pid-file without the ".newbin"
suffix. If the master process exits, then old master process renames
back its pid-file with the ".oldbin" suffix to the pid-file without
suffix.
*) Change: the "worker_connections" directive, new name of the
"connections" directive; now the directive specifies maximum number
of connections, but not maximum socket descriptor number.
*) Feature: SSL supports the session cache inside one worker process.
*) Feature: the "satisfy_any" directive.
*) Change: the ngx_http_access_module and ngx_http_auth_basic_module do
not run for subrequests.
*) Feature: the "worker_rlimit_nofile" and "worker_rlimit_sigpending"
directives.
*) Bugfix: if all backend using in load-balancing failed after one
error, then nginx did not try do connect to them during 60 seconds.
*) Bugfix: in IMAP/POP3 command argument parsing.
Thanks to Rob Mueller.
*) Bugfix: errors while using SSL in IMAP/POP3 proxy.
*) Bugfix: errors while using SSI and gzipping.
*) Bugfix: the "Expires" and "Cache-Control" header lines were omitted
from the 304 responses.
Thanks to Alexandr Kukushkin.
diff --git a/src/os/unix/ngx_channel.c b/src/os/unix/ngx_channel.c
index c052b60..01a0514 100644
--- a/src/os/unix/ngx_channel.c
+++ b/src/os/unix/ngx_channel.c
@@ -9,8 +9,9 @@
#include <ngx_channel.h>
-ngx_int_t ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
- ngx_log_t *log)
+ngx_int_t
+ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
+ ngx_log_t *log)
{
ssize_t n;
ngx_err_t err;
@@ -77,8 +78,8 @@
}
-ngx_int_t ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
- ngx_log_t *log)
+ngx_int_t
+ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size, ngx_log_t *log)
{
ssize_t n;
ngx_err_t err;
@@ -178,31 +179,40 @@
}
-ngx_int_t ngx_add_channel_event(ngx_cycle_t *cycle, ngx_fd_t fd,
- ngx_int_t event, ngx_event_handler_pt handler)
+ngx_int_t
+ngx_add_channel_event(ngx_cycle_t *cycle, ngx_fd_t fd, ngx_int_t event,
+ ngx_event_handler_pt handler)
{
ngx_event_t *ev, *rev, *wev;
ngx_connection_t *c;
- c = &cycle->connections[fd];
- rev = &cycle->read_events[fd];
- wev = &cycle->write_events[fd];
+ c = ngx_get_connection(fd, cycle->log);
+
+ if (c == NULL) {
+ return NGX_ERROR;
+ }
+
+ rev = c->read;
+ wev = c->write;
ngx_memzero(c, sizeof(ngx_connection_t));
- ngx_memzero(rev, sizeof(ngx_event_t));
- ngx_memzero(wev, sizeof(ngx_event_t));
-
- c->fd = fd;
- c->pool = cycle->pool;
c->read = rev;
c->write = wev;
-
+ c->fd = fd;
c->log = cycle->log;
+
+ c->pool = cycle->pool;
+
+ ngx_memzero(rev, sizeof(ngx_event_t));
+ ngx_memzero(wev, sizeof(ngx_event_t));
+
rev->log = cycle->log;
wev->log = cycle->log;
+
rev->index = NGX_INVALID_INDEX;
wev->index = NGX_INVALID_INDEX;
+
rev->data = c;
wev->data = c;
@@ -219,11 +229,13 @@
if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
if (ngx_add_conn(c) == NGX_ERROR) {
+ ngx_free_connection(c);
return NGX_ERROR;
}
} else {
if (ngx_add_event(ev, event, 0) == NGX_ERROR) {
+ ngx_free_connection(c);
return NGX_ERROR;
}
}
@@ -232,7 +244,8 @@
}
-void ngx_close_channel(ngx_fd_t *fd, ngx_log_t *log)
+void
+ngx_close_channel(ngx_fd_t *fd, ngx_log_t *log)
{
if (close(fd[0]) == -1) {
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "close() channel failed");
diff --git a/src/os/unix/ngx_channel.h b/src/os/unix/ngx_channel.h
index a8c8663..365d439 100644
--- a/src/os/unix/ngx_channel.h
+++ b/src/os/unix/ngx_channel.h
@@ -22,11 +22,11 @@
ngx_int_t ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
- ngx_log_t *log);
+ ngx_log_t *log);
ngx_int_t ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
- ngx_log_t *log);
+ ngx_log_t *log);
ngx_int_t ngx_add_channel_event(ngx_cycle_t *cycle, ngx_fd_t fd,
- ngx_int_t event, ngx_event_handler_pt handler);
+ ngx_int_t event, ngx_event_handler_pt handler);
void ngx_close_channel(ngx_fd_t *fd, ngx_log_t *log);
diff --git a/src/os/unix/ngx_errno.h b/src/os/unix/ngx_errno.h
index 310a1dc..e550788 100644
--- a/src/os/unix/ngx_errno.h
+++ b/src/os/unix/ngx_errno.h
@@ -33,6 +33,7 @@
#define NGX_ENOTCONN ENOTCONN
#define NGX_ETIMEDOUT ETIMEDOUT
#define NGX_ECONNREFUSED ECONNREFUSED
+#define NGX_ENAMETOOLONG ENAMETOOLONG
#define NGX_EHOSTUNREACH EHOSTUNREACH
#define NGX_ENOSYS ENOSYS
#define NGX_ECANCELED ECANCELED
diff --git a/src/os/unix/ngx_process.c b/src/os/unix/ngx_process.c
index eaf7ae4..7f25f91 100644
--- a/src/os/unix/ngx_process.c
+++ b/src/os/unix/ngx_process.c
@@ -94,7 +94,7 @@
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
"no more than %d processes can be spawned",
NGX_MAX_PROCESSES);
- return NGX_ERROR;
+ return NGX_INVALID_PID;
}
}
@@ -107,7 +107,7 @@
{
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"socketpair() failed while spawning \"%s\"", name);
- return NGX_ERROR;
+ return NGX_INVALID_PID;
}
ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
@@ -120,7 +120,7 @@
ngx_nonblocking_n " failed while spawning \"%s\"",
name);
ngx_close_channel(ngx_processes[s].channel, cycle->log);
- return NGX_ERROR;
+ return NGX_INVALID_PID;
}
if (ngx_nonblocking(ngx_processes[s].channel[1]) == -1) {
@@ -128,7 +128,7 @@
ngx_nonblocking_n " failed while spawning \"%s\"",
name);
ngx_close_channel(ngx_processes[s].channel, cycle->log);
- return NGX_ERROR;
+ return NGX_INVALID_PID;
}
on = 1;
@@ -136,14 +136,14 @@
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"ioctl(FIOASYNC) failed while spawning \"%s\"", name);
ngx_close_channel(ngx_processes[s].channel, cycle->log);
- return NGX_ERROR;
+ return NGX_INVALID_PID;
}
if (fcntl(ngx_processes[s].channel[0], F_SETOWN, ngx_pid) == -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"fcntl(F_SETOWN) failed while spawning \"%s\"", name);
ngx_close_channel(ngx_processes[s].channel, cycle->log);
- return NGX_ERROR;
+ return NGX_INVALID_PID;
}
if (fcntl(ngx_processes[s].channel[0], F_SETFD, FD_CLOEXEC) == -1) {
@@ -151,7 +151,7 @@
"fcntl(FD_CLOEXEC) failed while spawning \"%s\"",
name);
ngx_close_channel(ngx_processes[s].channel, cycle->log);
- return NGX_ERROR;
+ return NGX_INVALID_PID;
}
if (fcntl(ngx_processes[s].channel[1], F_SETFD, FD_CLOEXEC) == -1) {
@@ -159,7 +159,7 @@
"fcntl(FD_CLOEXEC) failed while spawning \"%s\"",
name);
ngx_close_channel(ngx_processes[s].channel, cycle->log);
- return NGX_ERROR;
+ return NGX_INVALID_PID;
}
ngx_channel = ngx_processes[s].channel[1];
@@ -180,7 +180,7 @@
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"fork() failed while spawning \"%s\"", name);
ngx_close_channel(ngx_processes[s].channel, cycle->log);
- return NGX_ERROR;
+ return NGX_INVALID_PID;
case 0:
ngx_pid = ngx_getpid();
diff --git a/src/os/unix/ngx_process.h b/src/os/unix/ngx_process.h
index 3684b15..06ff21c 100644
--- a/src/os/unix/ngx_process.h
+++ b/src/os/unix/ngx_process.h
@@ -13,6 +13,8 @@
typedef pid_t ngx_pid_t;
+#define NGX_INVALID_PID -1
+
typedef void (*ngx_spawn_proc_pt) (ngx_cycle_t *cycle, void *data);
typedef struct {
diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c
index 0c8fdd2..034b09f 100644
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -513,9 +513,10 @@
static ngx_uint_t
ngx_reap_childs(ngx_cycle_t *cycle)
{
- ngx_int_t i, n;
- ngx_uint_t live;
- ngx_channel_t ch;
+ ngx_int_t i, n;
+ ngx_uint_t live;
+ ngx_channel_t ch;
+ ngx_core_conf_t *ccf;
ch.command = NGX_CMD_CLOSE_CHANNEL;
ch.fd = -1;
@@ -575,7 +576,7 @@
if (ngx_spawn_process(cycle, ngx_processes[i].proc,
ngx_processes[i].data,
ngx_processes[i].name, i)
- == NGX_ERROR)
+ == NGX_INVALID_PID)
{
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
"can not respawn %s", ngx_processes[i].name);
@@ -615,6 +616,20 @@
}
if (ngx_processes[i].pid == ngx_new_binary) {
+
+ ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx,
+ ngx_core_module);
+
+ if (ngx_rename_file((char *) ccf->oldpid.data,
+ (char *) 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 the new binary process \"%s\" exited",
+ ccf->oldpid.data, ccf->pid.data, ngx_argv[0]);
+ }
+
ngx_new_binary = 0;
if (ngx_noaccepting) {
ngx_restart = 1;
@@ -795,6 +810,7 @@
sigset_t set;
ngx_int_t n;
ngx_uint_t i;
+ struct rlimit rlmt;
struct timeval tv;
ngx_core_conf_t *ccf;
ngx_listening_t *ls;
@@ -818,6 +834,30 @@
}
}
+ if (ccf->rlimit_nofile != NGX_CONF_UNSET) {
+ rlmt.rlim_cur = (rlim_t) ccf->rlimit_nofile;
+ rlmt.rlim_max = (rlim_t) ccf->rlimit_nofile;
+
+ if (setrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
+ ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
+ "setrlimit(RLIMIT_NOFILE, %i) failed",
+ ccf->rlimit_nofile);
+ }
+ }
+
+#ifdef RLIMIT_SIGPENDING
+ if (ccf->rlimit_sigpending != NGX_CONF_UNSET) {
+ rlmt.rlim_cur = (rlim_t) ccf->rlimit_sigpending;
+ rlmt.rlim_max = (rlim_t) ccf->rlimit_sigpending;
+
+ if (setrlimit(RLIMIT_SIGPENDING, &rlmt) == -1) {
+ ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
+ "setrlimit(RLIMIT_SIGPENDING, %i) failed",
+ ccf->rlimit_sigpending);
+ }
+ }
+#endif
+
if (setgid(ccf->group) == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
"setgid(%d) failed", ccf->group);
@@ -874,7 +914,7 @@
*/
ls = cycle->listening.elts;
for (i = 0; i < cycle->listening.nelts; i++) {
- ls[i].remain = 0;
+ ls[i].previous = NULL;
}
for (i = 0; ngx_modules[i]; i++) {
@@ -928,6 +968,7 @@
ngx_channel_handler(ngx_event_t *ev)
{
ngx_int_t n;
+ ngx_socket_t fd;
ngx_channel_t ch;
ngx_connection_t *c;
@@ -945,12 +986,17 @@
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel: %i", n);
if (n == NGX_ERROR) {
- if (close(c->fd) == -1) {
+
+ ngx_free_connection(c);
+
+ fd = c->fd;
+ c->fd = (ngx_socket_t) -1;
+
+ if (close(fd) == -1) {
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
"close() channel failed");
}
- c->fd = -1;
return;
}
@@ -1144,7 +1190,7 @@
ngx_worker_process_init(cycle, 0);
- ev = &cycle->read_events[ngx_channel];
+ ev = &cycle->read_events0[ngx_channel];
ngx_accept_mutex = NULL;