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;