changeset 323:ba876b26b76d

nginx-0.0.3-2004-04-21-22:54:33 import
author Igor Sysoev <igor@sysoev.ru>
date Wed, 21 Apr 2004 18:54:33 +0000
parents ab2f8c9a2a45
children 0ab66f4b6c4d
files auto/options src/core/nginx.c src/core/ngx_config.h src/core/ngx_times.c src/core/ngx_times.h src/event/modules/ngx_devpoll_module.c src/event/modules/ngx_epoll_module.c src/event/modules/ngx_kqueue_module.c src/event/modules/ngx_poll_module.c src/event/modules/ngx_rtsig_module.c src/event/modules/ngx_select_module.c src/event/ngx_event.c src/event/ngx_event.h src/event/ngx_event_accept.c src/event/ngx_event_connect.c src/http/modules/ngx_http_gzip_filter.c src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_parse.c src/http/ngx_http_request.c src/http/ngx_http_special_response.c src/os/unix/ngx_process_cycle.c src/os/unix/ngx_time.c src/os/unix/ngx_time.h src/os/win32/ngx_time.h
diffstat 25 files changed, 503 insertions(+), 232 deletions(-) [+]
line wrap: on
line diff
--- a/auto/options
+++ b/auto/options
@@ -123,3 +123,9 @@ if [ $help = yes ]; then
 
     exit 1
 fi
+
+
+if [ ".$PLATFORM" = ".win32" -a $EVENT_POLL = YES ]; then
+    EVENT_POLL=NO
+    echo "$0: warning: --with-poll_module option is ignored for win32"
+fi
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -86,7 +86,7 @@ int main(int argc, char *const *argv)
     ngx_core_conf_t   *ccf;
     ngx_master_ctx_t   ctx;
 
-#if __FreeBSD__
+#if defined __FreeBSD__
     ngx_debug_init();
 #endif
 
--- a/src/core/ngx_config.h
+++ b/src/core/ngx_config.h
@@ -2,29 +2,22 @@
 #define _NGX_CONFIG_H_INCLUDED_
 
 
-#if 0
-/* STUB to allocate a big ngx_connections */
-#undef  FD_SETSIZE
-#define FD_SETSIZE  5000
-#endif
-
-
-#if defined __DragonFly__ && !defined(__FreeBSD__)
+#if defined __DragonFly__ && !defined __FreeBSD__
 #define __FreeBSD__        4
 #define __FreeBSD_version  480101
 #endif
 
 
-#if defined (__FreeBSD__)
+#if defined __FreeBSD__
 #include <ngx_freebsd_config.h>
 
 
-#elif defined (__linux__)
+#elif defined __linux__
 #include <ngx_linux_config.h>
 
 
        /* Solaris */
-#elif defined (sun) && (defined (__svr4__) || defined (__SVR4))
+#elif defined sun && (defined __svr4__ || defined __SVR4)
 #include <ngx_solaris_config.h>
 
 
@@ -101,6 +94,8 @@ typedef int    ngx_flag_t;
 #define ngx_inline   inline
 #endif
 
+#define NGX_ACCEPT_THRESHOLD   50
+
 #ifndef INADDR_NONE  /* Solaris */
 #define INADDR_NONE  ((unsigned int) -1)
 #endif
--- a/src/core/ngx_times.c
+++ b/src/core/ngx_times.c
@@ -8,21 +8,27 @@ static ngx_mutex_t  *ngx_time_mutex;
 #endif
 
 
-time_t            ngx_cached_time;
-ngx_epoch_msec_t  ngx_elapsed_msec;
-ngx_epoch_msec_t  ngx_old_elapsed_msec;
-ngx_epoch_msec_t  ngx_start_msec;
+ngx_epoch_msec_t    ngx_elapsed_msec;
+ngx_epoch_msec_t    ngx_old_elapsed_msec;
+ngx_epoch_msec_t    ngx_start_msec;
 
-ngx_tm_t          ngx_cached_gmtime;
+volatile time_t     ngx_cached_time;
+
+volatile ngx_str_t  ngx_cached_err_log_time;
+volatile ngx_str_t  ngx_cached_http_time;
+volatile ngx_str_t  ngx_cached_http_log_time;
 
-static u_char     cached_err_log_time[] = "1970/09/28 12:00:00";
-ngx_str_t         ngx_cached_err_log_time;
+static ngx_tm_t     ngx_cached_gmtime;
+static ngx_int_t    ngx_gmtoff;
+
+static u_char       cached_err_log_time0[] = "1970/09/28 12:00:00";
+static u_char       cached_err_log_time1[] = "1970/09/28 12:00:00";
 
-static u_char     cached_http_time[] = "Mon, 28 Sep 1970 06:00:00 GMT";
-ngx_str_t         ngx_cached_http_time;
+static u_char       cached_http_time0[] = "Mon, 28 Sep 1970 06:00:00 GMT";
+static u_char       cached_http_time1[] = "Mon, 28 Sep 1970 06:00:00 GMT";
 
-static u_char     cached_http_log_time[] = "28/Sep/1970:12:00:00";
-ngx_str_t         ngx_cached_http_log_time;
+static u_char       cached_http_log_time0[] = "28/Sep/1970:12:00:00 +0600";
+static u_char       cached_http_log_time1[] = "28/Sep/1970:12:00:00 +0600";
 
 
 static char  *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fir", "Sat" };
@@ -39,9 +45,15 @@ void ngx_time_init()
     ngx_cached_gmtime.ngx_tm_zone = "GMT";
 #endif
 
-    ngx_cached_err_log_time.data = cached_err_log_time;
-    ngx_cached_http_time.data = cached_http_time;
-    ngx_cached_http_log_time.data = cached_http_log_time;
+    ngx_cached_err_log_time.len = sizeof(cached_err_log_time0) - 1;
+    ngx_cached_err_log_time.data = cached_err_log_time0;
+
+    ngx_cached_http_time.len = sizeof(cached_http_time0) - 1;
+    ngx_cached_http_time.data = cached_http_time0;
+
+    ngx_cached_http_log_time.len = sizeof(cached_http_log_time0) - 1;
+    ngx_cached_http_log_time.data = cached_http_log_time0;
+
     ngx_cached_time = 0;
 
     ngx_gettimeofday(&tv);
@@ -50,6 +62,10 @@ void ngx_time_init()
     ngx_old_elapsed_msec = 0;
     ngx_elapsed_msec = 0;
 
+#if !(WIN32)
+    tzset();
+#endif
+
     ngx_time_update(tv.tv_sec);
 }
 
@@ -70,7 +86,11 @@ ngx_int_t ngx_time_mutex_init(ngx_log_t 
 
 void ngx_time_update(time_t s)
 {
-    ngx_tm_t  tm;
+    char                   *p;
+    ngx_tm_t                tm;
+#if (WIN32)
+    TIME_ZONE_INFORMATION   tz;
+#endif
 
     if (ngx_cached_time == s) {
         return;
@@ -86,37 +106,88 @@ void ngx_time_update(time_t s)
 
     ngx_gmtime(ngx_cached_time, &ngx_cached_gmtime);
 
-    ngx_cached_http_time.len = ngx_snprintf((char *) ngx_cached_http_time.data,
-                                       sizeof("Mon, 28 Sep 1970 06:00:00 GMT"),
-                                       "%s, %02d %s %4d %02d:%02d:%02d GMT",
-                                       week[ngx_cached_gmtime.ngx_tm_wday],
-                                       ngx_cached_gmtime.ngx_tm_mday,
-                                       months[ngx_cached_gmtime.ngx_tm_mon - 1],
-                                       ngx_cached_gmtime.ngx_tm_year,
-                                       ngx_cached_gmtime.ngx_tm_hour,
-                                       ngx_cached_gmtime.ngx_tm_min,
-                                       ngx_cached_gmtime.ngx_tm_sec);
+
+    if (ngx_cached_http_time.data == cached_http_time0) {
+        p = cached_http_time1;
+    } else {
+        p = cached_http_time0;
+    }
+
+    ngx_snprintf(p, sizeof("Mon, 28 Sep 1970 06:00:00 GMT"),
+                 "%s, %02d %s %4d %02d:%02d:%02d GMT",
+                 week[ngx_cached_gmtime.ngx_tm_wday],
+                 ngx_cached_gmtime.ngx_tm_mday,
+                 months[ngx_cached_gmtime.ngx_tm_mon - 1],
+                 ngx_cached_gmtime.ngx_tm_year,
+                 ngx_cached_gmtime.ngx_tm_hour,
+                 ngx_cached_gmtime.ngx_tm_min,
+                 ngx_cached_gmtime.ngx_tm_sec);
+
+    ngx_cached_http_time.data = p;
+
+
+#if (WIN32)
+
+    /*
+     * we do not use GetLocalTime() because it does not return GMT offset,
+     * and our ngx_gmtime() is fast enough
+     */
+
+    if (GetTimeZoneInformation(&tz) != TIME_ZONE_ID_INVALID) {
+        ngx_gmtoff = - tz.Bias;
+    }
+
+    ngx_gmtime(ngx_cached_time + ngx_gmtoff * 60, &tm);
+
+#elif (SOLARIS)
+
+    ngx_gmtoff = (daylight) ? - altzone / 60: - timezone / 60;
+    ngx_gmtime(ngx_cached_time + ngx_gmtoff * 60, &tm);
+
+#elif defined __linux__
+
+    ngx_gmtoff = - timezone / 60 + daylight * 60;
+    ngx_gmtime(ngx_cached_time + ngx_gmtoff * 60, &tm);
+
+#else
 
     ngx_localtime(&tm);
+    ngx_gmtoff = tm.ngx_tm_gmtoff / 60;
 
-    ngx_cached_err_log_time.len = ngx_snprintf((char *)
-                                       ngx_cached_err_log_time.data,
-                                       sizeof("1970/09/28 12:00:00"),
-                                       "%4d/%02d/%02d %02d:%02d:%02d",
-                                       tm.ngx_tm_year, tm.ngx_tm_mon,
-                                       tm.ngx_tm_mday, tm.ngx_tm_hour,
-                                       tm.ngx_tm_min, tm.ngx_tm_sec);
+#endif
+
+
+    if (ngx_cached_err_log_time.data == cached_err_log_time0) {
+        p = cached_err_log_time1;
+    } else {
+        p = cached_err_log_time0;
+    }
+
+    ngx_snprintf(p, sizeof("1970/09/28 12:00:00"),
+                 "%4d/%02d/%02d %02d:%02d:%02d",
+                 tm.ngx_tm_year, tm.ngx_tm_mon,
+                 tm.ngx_tm_mday, tm.ngx_tm_hour,
+                 tm.ngx_tm_min, tm.ngx_tm_sec);
 
-    ngx_cached_http_log_time.len = ngx_snprintf((char *)
-                                       ngx_cached_http_log_time.data,
-                                       sizeof("28/Sep/1970:12:00:00"),
-                                       "%02d/%s/%d:%02d:%02d:%02d",
-                                       tm.ngx_tm_mday,
-                                       months[tm.ngx_tm_mon - 1],
-                                       tm.ngx_tm_year,
-                                       tm.ngx_tm_hour,
-                                       tm.ngx_tm_min,
-                                       tm.ngx_tm_sec);
+    ngx_cached_err_log_time.data = p;
+
+
+    if (ngx_cached_http_log_time.data == cached_http_log_time0) {
+        p = cached_http_log_time1;
+    } else {
+        p = cached_http_log_time0;
+    }
+
+    ngx_snprintf(p, sizeof("28/Sep/1970:12:00:00 +0600"),
+                 "%02d/%s/%d:%02d:%02d:%02d %c%02d%02d",
+                 tm.ngx_tm_mday, months[tm.ngx_tm_mon - 1],
+                 tm.ngx_tm_year, tm.ngx_tm_hour,
+                 tm.ngx_tm_min, tm.ngx_tm_sec,
+                 ngx_gmtoff < 0 ? '-' : '+',
+                 abs(ngx_gmtoff / 60), abs(ngx_gmtoff % 60));
+
+    ngx_cached_http_log_time.data = p;
+
 
 #if (NGX_THREADS)
     ngx_mutex_unlock(ngx_time_mutex);
--- a/src/core/ngx_times.h
+++ b/src/core/ngx_times.h
@@ -17,12 +17,12 @@ void ngx_gmtime(time_t t, ngx_tm_t *tp);
 #define ngx_time()   ngx_cached_time
 
 
-extern time_t            ngx_cached_time;
-extern ngx_str_t         ngx_cached_err_log_time;
-extern ngx_str_t         ngx_cached_http_time;
-extern ngx_str_t         ngx_cached_http_log_time;
+extern volatile time_t     ngx_cached_time;
+extern volatile ngx_str_t  ngx_cached_err_log_time;
+extern volatile ngx_str_t  ngx_cached_http_time;
+extern volatile ngx_str_t  ngx_cached_http_log_time;
 
-extern ngx_epoch_msec_t  ngx_start_msec;
+extern ngx_epoch_msec_t    ngx_start_msec;
 
 /*
  * msecs elapsed since ngx_start_msec in the current event cycle,
--- a/src/event/modules/ngx_devpoll_module.c
+++ b/src/event/modules/ngx_devpoll_module.c
@@ -313,7 +313,7 @@ int ngx_devpoll_process_events(ngx_cycle
 {
     int                 events;
     ngx_int_t           i;
-    ngx_uint_t          j, lock, expire;
+    ngx_uint_t          j, lock, accept_lock, expire;
     size_t              n;
     ngx_msec_t          timer;
     ngx_err_t           err;
@@ -346,21 +346,30 @@ int ngx_devpoll_process_events(ngx_cycle
         expire = 1;
     }
 
+    ngx_old_elapsed_msec = ngx_elapsed_msec;
+    accept_lock = 0;
+
     if (ngx_accept_mutex) {
-        if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
-            return NGX_ERROR;
-        }
+        if (ngx_accept_disabled > 0) {
+            ngx_accept_disabled--;
 
-        if (ngx_accept_mutex_held == 0
-            && (timer == NGX_TIMER_INFINITE || timer > ngx_accept_mutex_delay))
-        {
-            timer = ngx_accept_mutex_delay;
-            expire = 0;
+        } else {
+            if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
+                return NGX_ERROR;
+            } 
+
+            if (ngx_accept_mutex_held) {
+                accept_lock = 1;
+
+            } else if (timer == NGX_TIMER_INFINITE
+                       || timer > ngx_accept_mutex_delay)
+            {
+                timer = ngx_accept_mutex_delay;
+                expire = 0;
+            }
         }
     }
 
-    ngx_old_elapsed_msec = ngx_elapsed_msec;
-
     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    "devpoll timer: %d", timer);
 
@@ -493,30 +502,39 @@ int ngx_devpoll_process_events(ngx_cycle
             } else if (!c->read->accept) {
                 ngx_post_event(c->read);
 
-            } else {
+            } else if (ngx_accept_disabled <= 0) {
                 ngx_mutex_unlock(ngx_posted_events_mutex);
 
                 c->read->event_handler(c->read);
 
+                if (ngx_accept_disabled > 0) { 
+                    ngx_accept_mutex_unlock();
+                    accept_lock = 0;
+                }
+
                 if (i + 1 == events) {
                     lock = 0;
                     break;
                 }
 
                 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
-                    ngx_accept_mutex_unlock();
+                    if (accept_lock) {
+                        ngx_accept_mutex_unlock();
+                    }
                     return NGX_ERROR;
                 }
             }
         }
     }
 
+    if (accept_lock) {
+        ngx_accept_mutex_unlock();
+    }
+
     if (lock) {
         ngx_mutex_unlock(ngx_posted_events_mutex);
     }
 
-    ngx_accept_mutex_unlock();
-
     if (expire && delta) {
         ngx_event_expire_timers((ngx_msec_t) delta);
     }
--- a/src/event/modules/ngx_epoll_module.c
+++ b/src/event/modules/ngx_epoll_module.c
@@ -345,7 +345,7 @@ int ngx_epoll_process_events(ngx_cycle_t
     int                events;
     size_t             n;
     ngx_int_t          instance, i;
-    ngx_uint_t         lock, expire;
+    ngx_uint_t         lock, accept_lock, expire;
     ngx_err_t          err;
     ngx_log_t         *log;
     ngx_msec_t         timer;
@@ -377,17 +377,26 @@ int ngx_epoll_process_events(ngx_cycle_t
     }
 
     ngx_old_elapsed_msec = ngx_elapsed_msec;
+    accept_lock = 0;
 
     if (ngx_accept_mutex) {
-        if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
-            return NGX_ERROR;
-        }
+        if (ngx_accept_disabled > 0) {
+            ngx_accept_disabled--;
+
+        } else {
+            if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
+                return NGX_ERROR;
+            }
 
-        if (ngx_accept_mutex_held == 0
-            && (timer == NGX_TIMER_INFINITE || timer > ngx_accept_mutex_delay))
-        {
-            timer = ngx_accept_mutex_delay;
-            expire = 0;
+            if (ngx_accept_mutex_held) {
+                accept_lock = 1;
+
+            } else if (timer == NGX_TIMER_INFINITE
+                       || timer > ngx_accept_mutex_delay)
+            {
+                timer = ngx_accept_mutex_delay;
+                expire = 0;
+            }
         }
     }
 
@@ -513,30 +522,40 @@ int ngx_epoll_process_events(ngx_cycle_t
             } else if (!c->read->accept) {
                 ngx_post_event(c->read);
 
-            } else {
+            } else if (ngx_accept_disabled <= 0) {
+
                 ngx_mutex_unlock(ngx_posted_events_mutex);
 
                 c->read->event_handler(c->read);
 
+                if (ngx_accept_disabled > 0) {
+                    ngx_accept_mutex_unlock();
+                    accept_lock = 0;
+                }
+
                 if (i + 1 == events) {
                     lock = 0;
                     break;
                 }
 
                 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
-                    ngx_accept_mutex_unlock();
+                    if (accept_lock) {
+                        ngx_accept_mutex_unlock();
+                    }
                     return NGX_ERROR;
                 }
             }
         }
     }
 
+    if (accept_lock) {
+        ngx_accept_mutex_unlock();
+    }
+
     if (lock) {
         ngx_mutex_unlock(ngx_posted_events_mutex);
     }
 
-    ngx_accept_mutex_unlock();
-
     if (expire && delta) {
         ngx_event_expire_timers((ngx_msec_t) delta);
     }
--- a/src/event/modules/ngx_kqueue_module.c
+++ b/src/event/modules/ngx_kqueue_module.c
@@ -345,7 +345,7 @@ static ngx_int_t ngx_kqueue_process_even
 {
     int                events;
     ngx_int_t          i, instance;
-    ngx_uint_t         lock, expire;
+    ngx_uint_t         lock, accept_lock, expire;
     ngx_err_t          err;
     ngx_msec_t         timer;
     ngx_event_t       *ev;
@@ -384,17 +384,26 @@ static ngx_int_t ngx_kqueue_process_even
 
     ngx_old_elapsed_msec = ngx_elapsed_msec;
     expire = 1;
+    accept_lock = 0;
 
     if (ngx_accept_mutex) {
-        if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
-            return NGX_ERROR;
-        }
+        if (ngx_accept_disabled > 0) {
+            ngx_accept_disabled--;
+
+        } else {
+            if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
+                return NGX_ERROR;
+            }
 
-        if (ngx_accept_mutex_held == 0
-            && (timer == NGX_TIMER_INFINITE || timer > ngx_accept_mutex_delay))
-        {
-            timer = ngx_accept_mutex_delay;
-            expire = 0;
+            if (ngx_accept_mutex_held) {
+                accept_lock = 1;
+
+            } else if (timer == NGX_TIMER_INFINITE
+                       || timer > ngx_accept_mutex_delay)
+            {
+                timer = ngx_accept_mutex_delay;
+                expire = 0;
+            }
         }
     }
 
@@ -539,27 +548,40 @@ static ngx_int_t ngx_kqueue_process_even
             continue;
         }
 
+        if (ngx_accept_disabled > 0) {
+            continue;
+        }
+
         ngx_mutex_unlock(ngx_posted_events_mutex);
 
         ev->event_handler(ev);
 
+        if (ngx_accept_disabled > 0) {
+            ngx_accept_mutex_unlock();
+            accept_lock = 0;
+        }
+
         if (i + 1 == events) {
             lock = 0;
             break;
         }
 
         if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
-            ngx_accept_mutex_unlock();
+            if (accept_lock) {
+                ngx_accept_mutex_unlock();
+            }
             return NGX_ERROR;
         }
     }
 
+    if (accept_lock) {
+        ngx_accept_mutex_unlock();
+    }
+
     if (lock) {
         ngx_mutex_unlock(ngx_posted_events_mutex);
     }
 
-    ngx_accept_mutex_unlock();
-
     /* TODO: wake up worker thread */
 
     if (expire && delta) {
--- a/src/event/modules/ngx_poll_module.c
+++ b/src/event/modules/ngx_poll_module.c
@@ -304,23 +304,31 @@ int ngx_poll_process_events(ngx_cycle_t 
     ngx_old_elapsed_msec = ngx_elapsed_msec; 
 
 #if (NGX_DEBUG0)
-    for (i = 0; i < nevents; i++) {
-        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
-                       "poll: %d: fd:%d ev:%04X",
-                       i, event_list[i].fd, event_list[i].events);
+    if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) {
+        for (i = 0; i < nevents; i++) {
+            ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
+                           "poll: %d: fd:%d ev:%04X",
+                           i, event_list[i].fd, event_list[i].events);
+        }
     }
 #endif
 
     if (ngx_accept_mutex) {
-        if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
-            return NGX_ERROR;
-        }
+        if (ngx_accept_disabled > 0) {
+            ngx_accept_disabled--;
+
+        } else {
+            if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
+                return NGX_ERROR;
+            }
 
-        if (ngx_accept_mutex_held == 0 
-            && (timer == NGX_TIMER_INFINITE || timer > ngx_accept_mutex_delay))
-        {
-            timer = ngx_accept_mutex_delay;
-            expire = 0;
+            if (ngx_accept_mutex_held == 0
+                && (timer == NGX_TIMER_INFINITE
+                    || timer > ngx_accept_mutex_delay))
+            { 
+                timer = ngx_accept_mutex_delay;
+                expire = 0;
+            } 
         }
     }
 
@@ -543,6 +551,11 @@ int ngx_poll_process_events(ngx_cycle_t 
 
         ev->event_handler(ev);
 
+        if (ngx_accept_disabled > 0) {
+            lock = 0;
+            break;
+        }
+
         ev = ev->next;
 
         if (ev == NULL) {
@@ -557,13 +570,13 @@ int ngx_poll_process_events(ngx_cycle_t 
 
     }
 
+    ngx_accept_mutex_unlock();
+    accept_events = NULL;
+
     if (lock) {
         ngx_mutex_unlock(ngx_posted_events_mutex);
     }
 
-    ngx_accept_mutex_unlock();
-    accept_events = NULL;
-
     if (ready != 0) {
         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "poll ready != events");
     }
--- a/src/event/modules/ngx_rtsig_module.c
+++ b/src/event/modules/ngx_rtsig_module.c
@@ -221,15 +221,21 @@ int ngx_rtsig_process_events(ngx_cycle_t
     expire = 1;
 
     if (ngx_accept_mutex) {
-        if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
-            return NGX_ERROR;
-        }
+        if (ngx_accept_disabled > 0) {
+            ngx_accept_disabled--;
+
+        } else {
+            if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
+                return NGX_ERROR;
+            }
 
-        if (ngx_accept_mutex_held == 0
-            && (timer == NGX_TIMER_INFINITE || timer > ngx_accept_mutex_delay))
-        {
-            timer = ngx_accept_mutex_delay;
-            expire = 0;
+            if (ngx_accept_mutex_held == 0
+                && (timer == NGX_TIMER_INFINITE
+                    || timer > ngx_accept_mutex_delay))
+            {
+                timer = ngx_accept_mutex_delay;
+                expire = 0;
+            } 
         }
     }
 
@@ -299,7 +305,9 @@ int ngx_rtsig_process_events(ngx_cycle_t
                     c->read->event_handler(c->read);
 
                 } else if (c->read->accept) {
-                    c->read->event_handler(c->read);
+                    if (ngx_accept_disabled > 0) {
+                        c->read->event_handler(c->read);
+                    }
 
                 } else {
                     if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
@@ -367,7 +375,6 @@ int ngx_rtsig_process_events(ngx_cycle_t
         return NGX_ERROR;
     }
 
-
     ngx_accept_mutex_unlock();
 
     if (expire && delta) {
--- a/src/event/modules/ngx_select_module.c
+++ b/src/event/modules/ngx_select_module.c
@@ -284,15 +284,21 @@ static int ngx_select_process_events(ngx
 #if !(WIN32)
 
     if (ngx_accept_mutex) {
-        if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
-            return NGX_ERROR;
-        }
+        if (ngx_accept_disabled > 0) {
+            ngx_accept_disabled--;
+
+        } else {
+            if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
+                return NGX_ERROR;
+            }
 
-        if (ngx_accept_mutex_held == 0
-            && (timer == NGX_TIMER_INFINITE || timer > ngx_accept_mutex_delay))
-        {
-            timer = ngx_accept_mutex_delay;
-            expire = 0;
+            if (ngx_accept_mutex_held == 0
+                && (timer == NGX_TIMER_INFINITE
+                    || timer > ngx_accept_mutex_delay))
+            {
+                timer = ngx_accept_mutex_delay;
+                expire = 0;
+            }
         }
     }
 
@@ -311,11 +317,18 @@ static int ngx_select_process_events(ngx
 #endif
 
 #if (NGX_DEBUG)
-    for (i = 0; i < nevents; i++) {
-        ev = event_index[i];
-        c = ev->data;
-        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
-                       "select event: fd:%d wr:%d", c->fd, ev->write);
+    if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) {
+        for (i = 0; i < nevents; i++) {
+            ev = event_index[i];
+            c = ev->data;
+            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
+                           "select event: fd:%d wr:%d", c->fd, ev->write);
+        }
+
+#if !(WIN32)
+        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
+                       "max_fd: %d", max_fd);
+#endif
     }
 #endif
 
@@ -365,6 +378,11 @@ static int ngx_select_process_events(ngx
             ngx_gettimeofday(&tv);
             ngx_time_update(tv.tv_sec);
             deltas = tv.tv_usec / 1000;
+
+            ngx_elapsed_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000
+                                                              - ngx_start_msec;
+        } else {
+            ngx_elapsed_msec += delta;
         }
 
         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
@@ -375,6 +393,8 @@ static int ngx_select_process_events(ngx
         ngx_gettimeofday(&tv);
         ngx_time_update(tv.tv_sec);
 
+        ngx_elapsed_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000
+                                                              - ngx_start_msec;
         if (ready == 0) {
             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                           "select() returned no events without timeout");
@@ -523,6 +543,11 @@ static int ngx_select_process_events(ngx
 
         ev->event_handler(ev);
 
+        if (ngx_accept_disabled > 0) {
+            lock = 0;
+            break;
+        }
+
         ev = ev->next;
 
         if (ev == NULL) {
@@ -534,16 +559,15 @@ static int ngx_select_process_events(ngx
             ngx_accept_mutex_unlock();
             return NGX_ERROR;
         }
+    }
 
-    }
+    ngx_accept_mutex_unlock();
+    accept_events = NULL;
 
     if (lock) {
         ngx_mutex_unlock(ngx_posted_events_mutex);
     }
 
-    ngx_accept_mutex_unlock();
-    accept_events = NULL;
-
     if (ready != nready) {
         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "select ready != events");
     }
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -56,6 +56,7 @@ ngx_atomic_t                     *ngx_ac
 ngx_atomic_t                     *ngx_accept_mutex;
 ngx_uint_t                        ngx_accept_mutex_held;
 ngx_msec_t                        ngx_accept_mutex_delay;
+ngx_int_t                         ngx_accept_disabled;
 
 
 
@@ -464,13 +465,13 @@ static char *ngx_event_connections(ngx_c
 
     ngx_str_t  *value;
 
-    if (ecf->connections != NGX_CONF_UNSET) {
+    if (ecf->connections != NGX_CONF_UNSET_UINT) {
         return "is duplicate" ;
     }
 
     value = cf->args->elts;
     ecf->connections = ngx_atoi(value[1].data, value[1].len);
-    if (ecf->connections == NGX_ERROR) {
+    if (ecf->connections == (ngx_uint_t) NGX_ERROR) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                            "invalid number \"%s\"", value[1].data);
 
@@ -598,7 +599,7 @@ static void *ngx_event_create_conf(ngx_c
     ngx_test_null(ecf, ngx_palloc(cycle->pool, sizeof(ngx_event_conf_t)),
                   NGX_CONF_ERROR);
 
-    ecf->connections = NGX_CONF_UNSET;
+    ecf->connections = NGX_CONF_UNSET_UINT;
     ecf->use = NGX_CONF_UNSET;
     ecf->multi_accept = NGX_CONF_UNSET;
     ecf->accept_mutex = NGX_CONF_UNSET;
@@ -620,25 +621,25 @@ static char *ngx_event_init_conf(ngx_cyc
 
 #if (HAVE_KQUEUE)
 
-    ngx_conf_init_value(ecf->connections, DEFAULT_CONNECTIONS);
+    ngx_conf_init_unsigned_value(ecf->connections, DEFAULT_CONNECTIONS);
     ngx_conf_init_value(ecf->use, ngx_kqueue_module.ctx_index);
     ngx_conf_init_ptr_value(ecf->name, ngx_kqueue_module_ctx.name->data);
 
 #elif (HAVE_DEVPOLL)
 
-    ngx_conf_init_value(ecf->connections, DEFAULT_CONNECTIONS);
+    ngx_conf_init_unsigned_value(ecf->connections, DEFAULT_CONNECTIONS);
     ngx_conf_init_value(ecf->use, ngx_devpoll_module.ctx_index);
     ngx_conf_init_ptr_value(ecf->name, ngx_devpoll_module_ctx.name->data);
 
 #elif (HAVE_EPOLL)
 
-    ngx_conf_init_value(ecf->connections, DEFAULT_CONNECTIONS);
+    ngx_conf_init_unsigned_value(ecf->connections, DEFAULT_CONNECTIONS);
     ngx_conf_init_value(ecf->use, ngx_epoll_module.ctx_index);
     ngx_conf_init_ptr_value(ecf->name, ngx_epoll_module_ctx.name->data);
 
 #elif (HAVE_SELECT)
 
-    ngx_conf_init_value(ecf->connections,
+    ngx_conf_init_unsigned_value(ecf->connections,
           FD_SETSIZE < DEFAULT_CONNECTIONS ? FD_SETSIZE : DEFAULT_CONNECTIONS);
 
     ngx_conf_init_value(ecf->use, ngx_select_module.ctx_index);
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -381,7 +381,7 @@ extern ngx_event_actions_t   ngx_event_a
 
 
 typedef struct {
-    ngx_int_t     connections;
+    ngx_uint_t    connections;
     ngx_int_t     use;
 
     ngx_flag_t    multi_accept;
@@ -413,6 +413,7 @@ extern ngx_atomic_t          *ngx_accept
 extern ngx_atomic_t          *ngx_accept_mutex;
 extern ngx_uint_t             ngx_accept_mutex_held;
 extern ngx_msec_t             ngx_accept_mutex_delay;
+extern ngx_int_t              ngx_accept_disabled;
 
 
 #define ngx_accept_mutex_unlock()                                             \
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -125,9 +125,13 @@ void ngx_event_accept(ngx_event_t *ev)
             return;
         }
 
+
+        ngx_accept_disabled = (ngx_uint_t) s + NGX_ACCEPT_THRESHOLD
+                                                            - ecf->connections;
+
         /* disable warning: Win32 SOCKET is u_int while UNIX socket is int */
 
-        if ((unsigned) s >= (unsigned) ecf->connections) {
+        if ((ngx_uint_t) s >= ecf->connections) {
 
             ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
                           "accept() on %s returned socket #%d while "
@@ -140,8 +144,6 @@ void ngx_event_accept(ngx_event_t *ev)
                               ngx_close_socket_n "failed");
             }
 
-            /* TODO: disable temporary accept() event */
-
             ngx_destroy_pool(pool);
             return;
         }
--- a/src/event/ngx_event_connect.c
+++ b/src/event/ngx_event_connect.c
@@ -19,6 +19,7 @@ int ngx_event_connect_peer(ngx_peer_conn
     ngx_socket_t         s;
     ngx_event_t         *rev, *wev;
     ngx_connection_t    *c;
+    ngx_event_conf_t    *ecf;
     struct sockaddr_in   addr;
 
     now = ngx_time();
@@ -103,6 +104,29 @@ int ngx_event_connect_peer(ngx_peer_conn
         return NGX_ERROR;
     }
 
+
+    ecf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_core_module);
+
+    /* disable warning: Win32 SOCKET is u_int while UNIX socket is int */
+
+    if ((ngx_uint_t) s >= ecf->connections) {
+
+        ngx_log_error(NGX_LOG_ALERT, pc->log, 0,
+                      "socket() returned socket #%d while only %d "
+                      "connections was configured, closing the socket",
+                      s, ecf->connections);
+
+        if (ngx_close_socket(s) == -1) {
+            ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
+                          ngx_close_socket_n "failed");
+        }
+
+        /* TODO: sleep for some time */
+
+        return NGX_ERROR;
+    }
+
+
     if (pc->rcvbuf) {
         if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
                        (const void *) &pc->rcvbuf, sizeof(int)) == -1) {
--- a/src/http/modules/ngx_http_gzip_filter.c
+++ b/src/http/modules/ngx_http_gzip_filter.c
@@ -495,6 +495,9 @@ static int ngx_http_gzip_body_filter(ngx
                 && ctx->flush == Z_NO_FLUSH
                 && !ctx->redo) {
 
+                ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                               "gzip in: " PTR_FMT, ctx->in);
+
                 if (ctx->in == NULL) {
                     break;
                 }
@@ -505,6 +508,18 @@ static int ngx_http_gzip_body_filter(ngx
                 ctx->zstream.next_in = ctx->in_hunk->pos;
                 ctx->zstream.avail_in = ctx->in_hunk->last - ctx->in_hunk->pos;
 
+                ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                               "gzip in_hunk:" PTR_FMT " ni:" PTR_FMT " ai:%d",
+                               ctx->in_hunk,
+                               ctx->zstream.next_in, ctx->zstream.avail_in);
+
+                /* STUB */
+                if (ctx->in_hunk->last < ctx->in_hunk->pos) {
+                    ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                                  "zstream.avail_in is huge");
+                    return NGX_ERROR;
+                }
+
                 if (ctx->in_hunk->type & NGX_HUNK_LAST) {
                     ctx->flush = Z_FINISH;
 
@@ -547,11 +562,11 @@ static int ngx_http_gzip_body_filter(ngx
                 ctx->zstream.avail_out = conf->bufs.size;
             }
 
-            ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                           "deflate in: ni:%X no:%X ai:%d ao:%d fl:%d",
+            ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                           "deflate in: ni:%X no:%X ai:%d ao:%d fl:%d redo:%d",
                            ctx->zstream.next_in, ctx->zstream.next_out,
                            ctx->zstream.avail_in, ctx->zstream.avail_out,
-                           ctx->flush);
+                           ctx->flush, ctx->redo);
 
             rc = deflate(&ctx->zstream, ctx->flush);
             if (rc != Z_OK && rc != Z_STREAM_END) {
@@ -566,6 +581,10 @@ static int ngx_http_gzip_body_filter(ngx
                            ctx->zstream.avail_in, ctx->zstream.avail_out,
                            rc);
 
+            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                           "gzip in_hunk:" PTR_FMT " pos:" PTR_FMT,
+                           ctx->in_hunk, ctx->in_hunk->pos);
+
             ctx->in_hunk->pos = ctx->zstream.next_in;
             ctx->out_hunk->last = ctx->zstream.next_out;
 
@@ -576,95 +595,112 @@ static int ngx_http_gzip_body_filter(ngx
                 ctx->last_out = &cl->next;
                 ctx->redo = 1;
 
-            } else {
-                ctx->redo = 0;
+                continue;
+            }
 
-                if (ctx->flush == Z_SYNC_FLUSH) {
-                    ctx->out_hunk->type |= NGX_HUNK_FLUSH;
-                    ctx->flush = Z_NO_FLUSH;
+            ctx->redo = 0;
+
+            if (ctx->flush == Z_SYNC_FLUSH) {
+                ctx->out_hunk->type |= NGX_HUNK_FLUSH;
+                ctx->flush = Z_NO_FLUSH;
 
-                    ngx_alloc_link_and_set_hunk(cl, ctx->out_hunk, r->pool,
-                                                ngx_http_gzip_error(ctx));
-                    *ctx->last_out = cl;
-                    ctx->last_out = &cl->next;
+                ngx_alloc_link_and_set_hunk(cl, ctx->out_hunk, r->pool,
+                                            ngx_http_gzip_error(ctx));
+                *ctx->last_out = cl;
+                ctx->last_out = &cl->next;
 
-                    break;
+                break;
+            }
+
+            if (ctx->flush == Z_FINISH) {
 
-                } else if (ctx->flush == Z_FINISH) {
+                /* rc == Z_STREAM_END */
+
+                ctx->zin = ctx->zstream.total_in;
+                ctx->zout = 10 + ctx->zstream.total_out + 8;
 
-                    /* rc == Z_STREAM_END */
+                rc = deflateEnd(&ctx->zstream);
+                if (rc != Z_OK) {
+                    ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                                  "deflateEnd() failed: %d", rc);
+                    return ngx_http_gzip_error(ctx);
+                }
 
-                    ctx->zin = ctx->zstream.total_in;
-                    ctx->zout = 10 + ctx->zstream.total_out + 8;
+                ngx_pfree(r->pool, ctx->preallocated);
+
+                ctx->flush = Z_NO_FLUSH;
 
-                    rc = deflateEnd(&ctx->zstream);
-                    if (rc != Z_OK) {
-                        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                                      "deflateEnd() failed: %d", rc);
-                        return ngx_http_gzip_error(ctx);
-                    }
+                ngx_alloc_link_and_set_hunk(cl, ctx->out_hunk, r->pool,
+                                            ngx_http_gzip_error(ctx));
+                *ctx->last_out = cl;
+                ctx->last_out = &cl->next;
 
-                    ngx_pfree(r->pool, ctx->preallocated);
+                if (ctx->zstream.avail_out >= 8) {
+                    trailer = (struct gztrailer *) ctx->out_hunk->last;
+                    ctx->out_hunk->type |= NGX_HUNK_LAST;
+                    ctx->out_hunk->last += 8;
 
-                    ctx->flush = Z_NO_FLUSH;
+                } else {
+                    ngx_test_null(h, ngx_create_temp_hunk(r->pool, 8),
+                                  ngx_http_gzip_error(ctx));
 
-                    ngx_alloc_link_and_set_hunk(cl, ctx->out_hunk, r->pool,
+                    h->type |= NGX_HUNK_LAST;
+
+                    ngx_alloc_link_and_set_hunk(cl, h, r->pool,
                                                 ngx_http_gzip_error(ctx));
                     *ctx->last_out = cl;
                     ctx->last_out = &cl->next;
-
-                    if (ctx->zstream.avail_out >= 8) {
-                        trailer = (struct gztrailer *) ctx->out_hunk->last;
-                        ctx->out_hunk->type |= NGX_HUNK_LAST;
-                        ctx->out_hunk->last += 8;
-
-                    } else {
-                        ngx_test_null(h,
-                                      ngx_create_temp_hunk(r->pool, 8),
-                                      ngx_http_gzip_error(ctx));
-
-                        h->type |= NGX_HUNK_LAST;
-
-                        ngx_alloc_link_and_set_hunk(cl, h, r->pool,
-                                                    ngx_http_gzip_error(ctx));
-                        *ctx->last_out = cl;
-                        ctx->last_out = &cl->next;
-                        trailer = (struct gztrailer *) h->pos;
-                        h->last += 8;
-                    }
+                    trailer = (struct gztrailer *) h->pos;
+                    h->last += 8;
+                }
 
 #if (HAVE_LITTLE_ENDIAN)
-                    trailer->crc32 = ctx->crc32;
-                    trailer->zlen = ctx->zin;
+                trailer->crc32 = ctx->crc32;
+                trailer->zlen = ctx->zin;
 #else
-                    /* STUB */ Oops !
+                /* STUB */ Oops !
 #endif
 
-                    ctx->zstream.avail_in = 0;
-                    ctx->zstream.avail_out = 0;
+                ctx->zstream.avail_in = 0;
+                ctx->zstream.avail_out = 0;
 
-                    ctx->done = 1;
+                ctx->done = 1;
 
 #if 0
-                    ngx_http_delete_ctx(r, ngx_http_gzip_filter_module);
+                ngx_http_delete_ctx(r, ngx_http_gzip_filter_module);
 #endif
 
-                    break;
+                break;
+            }
 
-                } else if (conf->no_buffer && ctx->in == NULL) {
-                    ngx_alloc_link_and_set_hunk(cl, ctx->out_hunk, r->pool,
-                                                ngx_http_gzip_error(ctx));
-                    *ctx->last_out = cl;
-                    ctx->last_out = &cl->next;
+            if (conf->no_buffer && ctx->in == NULL) {
+                ngx_alloc_link_and_set_hunk(cl, ctx->out_hunk, r->pool,
+                                            ngx_http_gzip_error(ctx));
+                *ctx->last_out = cl;
+                ctx->last_out = &cl->next;
 
-                    break;
-                }
+                break;
             }
         }
 
+        if (ctx->out) {
+            if (last == NGX_AGAIN) {
+                return last;
+            }
+
+        } else {
+            if (last == NGX_NONE) {
+                return NGX_OK;
+            }
+
+            return last;
+        }
+
+#if 0
         if (ctx->out == NULL && last != NGX_NONE) {
             return last;
         }
+#endif
 
         last = ngx_http_next_body_filter(r, ctx->out);
 
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1449,7 +1449,8 @@ static char *ngx_set_error_page(ngx_conf
 {
     ngx_http_core_loc_conf_t *lcf = conf;
 
-    ngx_uint_t            i;
+    int                   overwrite;
+    ngx_uint_t            i, n;
     ngx_str_t            *value;
     ngx_http_err_page_t  *err;
 
@@ -1463,8 +1464,35 @@ static char *ngx_set_error_page(ngx_conf
 
     value = cf->args->elts;
 
-    for (i = 1; i < cf->args->nelts - 1; i++) {
-        ngx_test_null(err, ngx_push_array(lcf->error_pages), NGX_CONF_ERROR);
+    i = cf->args->nelts - 2;
+
+    if (value[i].data[0] == '=') {
+        if (i == 1) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "invalid value \"%s\"", value[i].data);
+            return NGX_CONF_ERROR;
+        }
+
+        overwrite = ngx_atoi(&value[i].data[1], value[i].len - 1);
+
+        if (overwrite == NGX_ERROR) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "invalid value \"%s\"", value[i].data);
+            return NGX_CONF_ERROR;
+        }
+
+        n = 2;
+
+    } else {
+        overwrite = 0;
+        n = 1;
+    }
+
+    for (i = 1; i < cf->args->nelts - n; i++) {
+        if (!(err = ngx_push_array(lcf->error_pages))) {
+            return NGX_CONF_ERROR;
+        }
+
         err->code = ngx_atoi(value[i].data, value[i].len);
         if (err->code == NGX_ERROR) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -1479,6 +1507,7 @@ static char *ngx_set_error_page(ngx_conf
             return NGX_CONF_ERROR;
         }
 
+        err->overwrite = overwrite;
         err->uri = value[cf->args->nelts - 1];
     }
 
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -106,6 +106,7 @@ typedef struct {
 
 typedef struct {
     int        code;
+    int        overwrite;
     ngx_str_t  uri;
 } ngx_http_err_page_t;
 
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -46,6 +46,10 @@ ngx_int_t ngx_http_parse_request_line(ng
         case sw_start:
             r->request_start = p - 1;
 
+            if (ch == CR || ch == LF) {
+                break;
+            }
+
             if (ch < 'A' || ch > 'Z') {
                 return NGX_HTTP_PARSE_INVALID_METHOD;
             }
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -728,8 +728,10 @@ static void ngx_http_process_request_hea
 
             /* there was error while a header line parsing */
 
-#if (NGX_LOG_DEBUG)
-            if (rc == NGX_HTTP_PARSE_INVALID_HEADER) {
+#if (NGX_DEBUG)
+            if (rc == NGX_HTTP_PARSE_INVALID_HEADER
+                && (rev->log->log_level & NGX_LOG_DEBUG_HTTP))
+            {
                 u_char *p;
                 for (p = r->header_name_start;
                      p < r->header_in->last - 1;
@@ -1249,12 +1251,6 @@ static void ngx_http_set_keepalive(ngx_h
     wev->event_handler = ngx_http_empty_handler;
 
 
-    /* skip the tralling "\r\n" before the possible pipelined request */
-
-    while (h->pos < h->last && (*h->pos == CR || *h->pos == LF)) {
-        h->pos++;
-    }
-
     if (h->pos < h->last) {
 
         /*
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -214,7 +214,11 @@ int ngx_http_special_response_handler(ng
         err_page = clcf->error_pages->elts;
         for (i = 0; i < clcf->error_pages->nelts; i++) {
             if (err_page[i].code == error) {
-                r->err_status = error;
+                if (err_page[i].overwrite) {
+                    r->err_status = err_page[i].overwrite;
+                } else {
+                    r->err_status = error;
+                }
                 r->err_ctx = r->ctx;
                 return ngx_http_internal_redirect(r, &err_page[i].uri, NULL);
             }
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -494,6 +494,7 @@ static void ngx_worker_process_cycle(ngx
         }
 
         if (ngx_quit) {
+            ngx_quit = 0;
             ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
                           "gracefully shutting down");
             ngx_setproctitle("worker process is shutting down");
@@ -505,9 +506,9 @@ static void ngx_worker_process_cycle(ngx
         }
 
         if (ngx_reopen) {
+            ngx_reopen = 0;
             ngx_log_error(NGX_LOG_INFO, cycle->log, 0, "reopen logs");
             ngx_reopen_files(cycle, -1);
-            ngx_reopen = 0;
         }
     }
 }
--- a/src/os/unix/ngx_time.c
+++ b/src/os/unix/ngx_time.c
@@ -7,12 +7,12 @@ void ngx_localtime(ngx_tm_t *tm)
 {
 #if (HAVE_LOCALTIME_R)
 
-    localtime_r(&ngx_cached_time, tm);
+    localtime_r((time_t *) &ngx_cached_time, tm);
 
 #else
     ngx_tm_t  *t;
 
-    t = localtime(&ngx_cached_time);
+    t = localtime((time_t *) &ngx_cached_time);
     *tm = *t;
 
 #endif
--- a/src/os/unix/ngx_time.h
+++ b/src/os/unix/ngx_time.h
@@ -20,6 +20,7 @@ typedef struct tm      ngx_tm_t;
 #define ngx_tm_mon     tm_mon
 #define ngx_tm_year    tm_year
 #define ngx_tm_wday    tm_wday
+#define ngx_tm_gmtoff  tm_gmtoff
 
 #ifndef SOLARIS
 #define ngx_tm_zone    tm_zone
@@ -41,7 +42,4 @@ void ngx_localtime(ngx_tm_t *tm);
 #define ngx_msleep(ms)        usleep(ms * 1000)
 
 
-extern time_t  ngx_cached_time;
-
-
 #endif /* _NGX_TIME_H_INCLUDED_ */
--- a/src/os/win32/ngx_time.h
+++ b/src/os/win32/ngx_time.h
@@ -33,7 +33,6 @@ typedef FILETIME       ngx_mtime_t;
 
 
 #define ngx_msleep     Sleep
-#define ngx_localtime  GetLocalTime
 
 
 void ngx_gettimeofday(struct timeval *tp);