changeset 391:b670db10cbbd

nginx-0.0.7-2004-07-14-20:01:42 import
author Igor Sysoev <igor@sysoev.ru>
date Wed, 14 Jul 2004 16:01:42 +0000
parents 1471c6fb108a
children d1222d46b3f9
files auto/modules auto/sources src/event/modules/ngx_rtsig_module.c src/http/modules/ngx_http_ssl_filter.c src/http/modules/ngx_http_ssl_filter.h src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_header_filter.c src/http/ngx_http_write_filter.c src/os/unix/ngx_channel.c src/os/unix/ngx_channel.h src/os/unix/ngx_freebsd_init.c src/os/unix/ngx_linux.h src/os/unix/ngx_linux_init.c src/os/unix/ngx_process.c src/os/unix/ngx_process.h src/os/unix/ngx_process_cycle.c src/os/unix/ngx_pthread_thread.c src/os/unix/ngx_solaris_init.c
diffstat 19 files changed, 238 insertions(+), 147 deletions(-) [+]
line wrap: on
line diff
--- a/auto/modules
+++ b/auto/modules
@@ -41,7 +41,33 @@ if [ $TEST_BUILD_RTSIG = YES ]; then
 fi
 
 
+# the filter order is important
+#     ngx_http_write_filter
+#     ngx_http_ssl_filter
+#     ngx_http_header_filter
+#     ngx_http_chunked_filter
+#     ngx_http_range_header_filter
+#     ngx_http_gzip_filter
+#     ngx_http_charset_filter
+#     ngx_http_ssi_filter
+#     ngx_http_headers_filter
+#     ngx_http_copy_filter
+#     ngx_http_range_body_filter
+#     ngx_http_not_modified_filter
+
+HTTP_FILTER_MODULES="$HTTP_WRITE_FILTER_MODULE"
+
+if [ $HTTP_SSL = YES ]; then
+    have=NGX_HTTP_SSL . auto/have
+    HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_SSL_FILTER_MODULE"
+    HTTP_DEPS="$HTTP_DEPS $HTTP_SSL_DEPS"
+    HTTP_SRCS="$HTTP_SRCS $HTTP_SSL_SRCS"
+    # STUB: move to auto/libs/ssl
+    CORE_LIBS="$CORE_LIBS -lssl -lcrypto"
+fi
+
 HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES \
+                     $HTTP_HEADER_FILTER_MODULE \
                      $HTTP_CHUNKED_FILTER_MODULE \
                      $HTTP_RANGE_HEADER_FILTER_MODULE"
 
@@ -58,15 +84,6 @@ if [ $HTTP_CHARSET = YES ]; then
     HTTP_SRCS="$HTTP_SRCS $HTTP_CHARSET_SRCS"
 fi
 
-if [ $HTTP_SSL = YES ]; then
-    have=NGX_HTTP_SSL . auto/have
-    HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_SSL_FILTER_MODULE"
-    HTTP_DEPS="$HTTP_DEPS $HTTP_SSL_DEPS"
-    HTTP_SRCS="$HTTP_SRCS $HTTP_SSL_SRCS"
-    # STUB: move to auto/libs/ssl
-    CORE_LIBS="$CORE_LIBS -lssl -lcrypto"
-fi
-
 if [ $HTTP_SSI = YES ]; then
     have=NGX_HTTP_SSI . auto/have
     HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_SSI_FILTER_MODULE"
--- a/auto/sources
+++ b/auto/sources
@@ -190,8 +190,8 @@ HTTP_MODULES="ngx_http_module \
 
 HTTP_FILE_CACHE_MODULE=ngx_http_cache_module
 
-HTTP_FILTER_MODULES="ngx_http_write_filter_module \
-            ngx_http_header_filter_module"
+HTTP_WRITE_FILTER_MODULE="ngx_http_write_filter_module"
+HTTP_HEADER_FILTER_MODULE="ngx_http_header_filter_module"
 
 HTTP_CHUNKED_FILTER_MODULE=ngx_http_chunked_filter_module
 HTTP_HEADERS_FILTER_MODULE=ngx_http_headers_filter_module
--- a/src/event/modules/ngx_rtsig_module.c
+++ b/src/event/modules/ngx_rtsig_module.c
@@ -23,6 +23,8 @@ int sigtimedwait(const sigset_t *set, si
     return -1;
 }
 
+int ngx_linux_rtsig_max;
+
 #endif
 
 
@@ -45,6 +47,8 @@ static ngx_int_t ngx_rtsig_process_overf
 
 static void *ngx_rtsig_create_conf(ngx_cycle_t *cycle);
 static char *ngx_rtsig_init_conf(ngx_cycle_t *cycle, void *conf);
+static char *ngx_check_ngx_overflow_threshold_bounds(ngx_conf_t *cf,
+                                                     void *post, void *data);
 
 
 static sigset_t        set;
@@ -55,7 +59,7 @@ static struct pollfd  *overflow_list;
 static ngx_str_t      rtsig_name = ngx_string("rtsig");
 
 static ngx_conf_num_bounds_t  ngx_overflow_threshold_bounds = {
-    ngx_conf_check_num_bounds, 2, 10
+    ngx_check_ngx_overflow_threshold_bounds, 2, 10
 };
 
 
@@ -644,6 +648,7 @@ static ngx_int_t ngx_rtsig_process_overf
             rev = c->read;
 
             if (rev->active
+                && !rev->closed
                 && rev->event_handler
                 && (overflow_list[i].revents
                                           & (POLLIN|POLLERR|POLLHUP|POLLNVAL)))
@@ -663,6 +668,7 @@ static ngx_int_t ngx_rtsig_process_overf
             wev = c->write;
 
             if (wev->active
+                && !wev->closed
                 && wev->event_handler
                 && (overflow_list[i].revents
                                          & (POLLOUT|POLLERR|POLLHUP|POLLNVAL)))
@@ -686,39 +692,58 @@ static ngx_int_t ngx_rtsig_process_overf
 
         if (tested >= rtscf->overflow_test) {
 
-            /*
-             * Check the current rt queue length to prevent the new overflow.
-             *
-             * Learn the /proc/sys/kernel/rtsig-max value because
-             * it can be changed sisnce the last checking.
-             */
+            if (ngx_linux_rtsig_max) {
+
+                /*
+                 * Check the current rt queue length to prevent
+                 * the new overflow.
+                 *
+                 * Learn the /proc/sys/kernel/rtsig-max value because
+                 * it can be changed sisnce the last checking.
+                 */
 
-            name[0] = CTL_KERN;
-            name[1] = KERN_RTSIGMAX;
-            len = sizeof(rtsig_max);
-            if (sysctl(name, sizeof(name), &rtsig_max, &len, NULL, 0) == -1) {
-                ngx_log_error(NGX_LOG_ALERT, cycle->log, errno,
-                              "sysctl(KERN_RTSIGMAX) failed");
-                return NGX_ERROR;
-            }
+                name[0] = CTL_KERN;
+                name[1] = KERN_RTSIGMAX;
+                len = sizeof(rtsig_max);
+                if (sysctl(name, sizeof(name), &rtsig_max, &len, NULL, 0) == -1)
+                {
+                    ngx_log_error(NGX_LOG_ALERT, cycle->log, errno,
+                                  "sysctl(KERN_RTSIGMAX) failed");
+                    return NGX_ERROR;
+                }
 
-            name[0] = CTL_KERN;
-            name[1] = KERN_RTSIGNR;
-            len = sizeof(rtsig_nr);
-            if (sysctl(name, sizeof(name), &rtsig_nr, &len, NULL, 0) == -1) {
-                ngx_log_error(NGX_LOG_ALERT, cycle->log, errno,
-                              "sysctl(KERN_RTSIGNR) failed");
-                return NGX_ERROR;
-            }
+                name[0] = CTL_KERN;
+                name[1] = KERN_RTSIGNR;
+                len = sizeof(rtsig_nr);
+                if (sysctl(name, sizeof(name), &rtsig_nr, &len, NULL, 0) == -1)
+                {
+                    ngx_log_error(NGX_LOG_ALERT, cycle->log, errno,
+                                  "sysctl(KERN_RTSIGNR) failed");
+                    return NGX_ERROR;
+                }
+
+                /*
+                 * drain rt signal queue if the /proc/sys/kernel/rtsig-nr
+                 * is bigger than
+                 *    /proc/sys/kernel/rtsig-max / rtsig_overflow_threshold
+                 */
 
-            /*
-             * drain rt signal queue if the /proc/sys/kernel/rtsig-nr is bigger
-             * than "/proc/sys/kernel/rtsig-max / rtsig_overflow_threshold"
-             */
+                if (rtsig_max / rtscf->overflow_threshold < rtsig_nr) {
+                    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
+                                   "rtsig queue state: %d/%d",
+                                   rtsig_nr, rtsig_max);
+                    while (ngx_rtsig_process_events(cycle) == NGX_OK) {
+                        /* void */
+                    }
+                }
 
-            if (rtsig_max / rtscf->overflow_threshold < rtsig_nr) {
-                ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
-                               "rtsig queue state: %d/%d", rtsig_nr, rtsig_max);
+            } else {
+
+                /*
+                 * Linux has not KERN_RTSIGMAX since 2.6.6-mm2
+                 * so drain rt signal queue unconditionally
+                 */
+
                 while (ngx_rtsig_process_events(cycle) == NGX_OK) { /* void */ }
             }
 
@@ -774,3 +799,18 @@ static char *ngx_rtsig_init_conf(ngx_cyc
 
     return NGX_CONF_OK;
 }
+
+
+static char *ngx_check_ngx_overflow_threshold_bounds(ngx_conf_t *cf,
+                                                     void *post, void *data)
+{
+    if (ngx_linux_rtsig_max) {
+        return ngx_conf_check_num_bounds(cf, post, data);
+    }
+
+    ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+                       "\"rtsig_overflow_threshold\" is not supported "
+                       "since Linux 2.6.6-mm2, ignored");
+
+    return NGX_CONF_OK;
+}
--- a/src/http/modules/ngx_http_ssl_filter.c
+++ b/src/http/modules/ngx_http_ssl_filter.c
@@ -22,12 +22,12 @@ typedef struct {
 
 typedef struct {
     SSL       *ssl;
-
-    unsigned   accepted;
 } ngx_http_ssl_ctx_t;
 
 
 static ngx_http_ssl_ctx_t *ngx_http_ssl_create_ctx(ngx_http_request_t *r);
+static ngx_chain_t *ngx_http_ssl_write(ngx_http_request_t *r, ngx_chain_t *in,
+                                       off_t limit);
 static void ngx_http_ssl_error(ngx_uint_t level, ngx_log_t *log, int err,
                                char *fmt, ...);
 static void *ngx_http_ssl_create_srv_conf(ngx_conf_t *cf);
@@ -152,7 +152,7 @@ ngx_int_t ngx_http_ssl_read(ngx_http_req
     }
 
     ngx_http_ssl_error(NGX_LOG_ALERT, r->connection->log, rc,
-                       "SSL_accept() failed");
+                       "SSL_read() failed");
 
     SSL_set_shutdown(ctx->ssl, SSL_RECEIVED_SHUTDOWN);
 
@@ -160,11 +160,8 @@ ngx_int_t ngx_http_ssl_read(ngx_http_req
 }
 
 
-ngx_int_t ngx_http_ssl_write(ngx_http_request_t *r, ngx_chain_t *in,
-                             off_t limit)
+ngx_int_t ngx_http_ssl_writer(ngx_http_request_t *r, ngx_chain_t *in)
 {
-    int                  rc;
-    size_t               send, size;
     ngx_http_ssl_ctx_t  *ctx;
 
     ctx = ngx_http_get_module_ctx(r, ngx_http_ssl_filter_module);
@@ -175,7 +172,12 @@ ngx_int_t ngx_http_ssl_write(ngx_http_re
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                        "SSL_shutdown: %d", rc);
 
+        if (rc == 0) {
+            return NGX_AGAIN;
+        }
+
         if (rc == 1) {
+            SSL_free(ctx->ssl);
             return NGX_OK;
         }
 
@@ -188,9 +190,28 @@ ngx_int_t ngx_http_ssl_write(ngx_http_re
             return NGX_AGAIN;
         }
 
+        ngx_http_ssl_error(NGX_LOG_ALERT, r->connection->log, rc,
+                           "SSL_shutdown() failed");
+
         return NGX_ERROR;
     }
 
+    ch = ngx_http_ssl_write(r, ctx, in, 0);
+
+    return NGX_OK;
+}
+
+
+static ngx_chain_t *ngx_http_ssl_write(ngx_http_request_t *r,
+                                       ngx_http_ssl_ctx_t *ctx,
+                                       ngx_chain_t *in,
+                                       off_t limit)
+{
+    int                  rc;
+    size_t               send, size;
+
+    ctx = ngx_http_get_module_ctx(r, ngx_http_ssl_filter_module);
+
     send = 0;
 
     for (/* void */; in; in = in->next) {
@@ -205,9 +226,20 @@ ngx_int_t ngx_http_ssl_write(ngx_http_re
         }
 
         rc = SSL_write(ctx->ssl, in->buf->pos, size);
+
+        if (rc > 0) {
+            in->buf->pos += rc;
+
+            if (rc == size) {
+                continue;
+            }
+
+            r->connection->write->ready = 0;
+            return in;
+        }
     }
 
-    return NGX_OK;
+    return in;
 }
 
 
--- a/src/http/modules/ngx_http_ssl_filter.h
+++ b/src/http/modules/ngx_http_ssl_filter.h
@@ -14,6 +14,8 @@
 
 
 ngx_int_t ngx_http_ssl_read(ngx_http_request_t *r, u_char *buf, size_t n);
+ngx_int_t ngx_http_ssl_writer(ngx_http_request_t *r, ngx_chain_t *in);
+
 void ngx_http_ssl_close_connection(SSL *ssl, ngx_log_t *log);
 
 
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -206,6 +206,20 @@ static ngx_command_t  ngx_http_core_comm
       offsetof(ngx_http_core_loc_conf_t, send_lowat),
       &ngx_http_lowat_post },
 
+    { ngx_string("postpone_output"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_size_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_core_loc_conf_t, postpone_output),
+      NULL },
+
+    { ngx_string("limit_rate"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_size_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_core_loc_conf_t, limit_rate),
+      NULL },
+
     { ngx_string("keepalive_timeout"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_msec_slot,
@@ -1251,6 +1265,8 @@ static void *ngx_http_core_create_loc_co
     lcf->tcp_nopush = NGX_CONF_UNSET;
     lcf->send_timeout = NGX_CONF_UNSET_MSEC;
     lcf->send_lowat = NGX_CONF_UNSET_SIZE;
+    lcf->postpone_output = NGX_CONF_UNSET_SIZE;
+    lcf->limit_rate = NGX_CONF_UNSET_SIZE;
     lcf->discarded_buffer_size = NGX_CONF_UNSET_SIZE;
     lcf->keepalive_timeout = NGX_CONF_UNSET_MSEC;
     lcf->lingering_time = NGX_CONF_UNSET_MSEC;
@@ -1334,6 +1350,9 @@ static char *ngx_http_core_merge_loc_con
     ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0);
     ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 60000);
     ngx_conf_merge_size_value(conf->send_lowat, prev->send_lowat, 0);
+    ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output,
+                              1460);
+    ngx_conf_merge_size_value(conf->limit_rate, prev->limit_rate, 0);
     ngx_conf_merge_size_value(conf->discarded_buffer_size,
                               prev->discarded_buffer_size, 1500);
     ngx_conf_merge_msec_value(conf->keepalive_timeout,
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -134,6 +134,8 @@ typedef struct {
     size_t        discarded_buffer_size;   /* discarded_buffer_size */
     size_t        client_body_buffer_size; /* client_body_buffer_size */
     size_t        send_lowat;              /* send_lowat */
+    size_t        postpone_output;         /* postpone_output */
+    size_t        limit_rate;              /* limit_rate */
 
     ngx_msec_t    client_body_timeout;     /* client_body_timeout */
     ngx_msec_t    send_timeout;            /* send_timeout */
--- a/src/http/ngx_http_header_filter.c
+++ b/src/http/ngx_http_header_filter.c
@@ -33,6 +33,9 @@ ngx_module_t  ngx_http_header_filter_mod
 };
 
 
+static ngx_http_output_body_filter_pt    write_filter;
+
+
 static char server_string[] = "Server: " NGINX_VER CRLF;
 
 
@@ -355,7 +358,7 @@ static ngx_int_t ngx_http_header_filter(
     ln->buf = b;
     ln->next = NULL;
 
-    return ngx_http_write_filter(r, ln);
+    return write_filter(r, ln);
 }
 
 
@@ -363,5 +366,7 @@ static ngx_int_t ngx_http_header_filter_
 {
     ngx_http_top_header_filter = ngx_http_header_filter;
 
+    write_filter = ngx_http_top_body_filter;
+
     return NGX_OK;
 }
--- a/src/http/ngx_http_write_filter.c
+++ b/src/http/ngx_http_write_filter.c
@@ -6,42 +6,13 @@
 
 
 typedef struct {
-    size_t  postpone_output;         /* postpone_output */
-    size_t  limit_rate;              /* limit_rate */
-} ngx_http_write_filter_conf_t;
-
-
-typedef struct {
     ngx_chain_t  *out;
 } ngx_http_write_filter_ctx_t;
 
 
-static void *ngx_http_write_filter_create_conf(ngx_conf_t *cf);
-static char *ngx_http_write_filter_merge_conf(ngx_conf_t *cf,
-                                              void *parent, void *child);
 static ngx_int_t ngx_http_write_filter_init(ngx_cycle_t *cycle);
 
 
-static ngx_command_t  ngx_http_write_filter_commands[] = {
-
-    { ngx_string("postpone_output"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_size_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_write_filter_conf_t, postpone_output),
-      NULL },
-
-    { ngx_string("limit_rate"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_size_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_write_filter_conf_t, limit_rate),
-      NULL },
-
-      ngx_null_command
-};
-
-
 ngx_http_module_t  ngx_http_write_filter_module_ctx = {
     NULL,                                  /* pre conf */
 
@@ -51,15 +22,15 @@ ngx_http_module_t  ngx_http_write_filter
     NULL,                                  /* create server configuration */
     NULL,                                  /* merge server configuration */
 
-    ngx_http_write_filter_create_conf,     /* create location configuration */
-    ngx_http_write_filter_merge_conf       /* merge location configuration */
+    NULL,                                  /* create location configuration */
+    NULL,                                  /* merge location configuration */
 };
 
 
 ngx_module_t  ngx_http_write_filter_module = {
     NGX_MODULE,
     &ngx_http_write_filter_module_ctx,     /* module context */
-    ngx_http_write_filter_commands,        /* module directives */
+    NULL,                                  /* module directives */
     NGX_HTTP_MODULE,                       /* module type */
     ngx_http_write_filter_init,            /* init module */
     NULL                                   /* init process */
@@ -68,11 +39,11 @@ ngx_module_t  ngx_http_write_filter_modu
 
 ngx_int_t ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
 {
-    int                            last;
-    off_t                          size, flush, sent;
-    ngx_chain_t                   *cl, *ln, **ll, *chain;
-    ngx_http_write_filter_ctx_t   *ctx;
-    ngx_http_write_filter_conf_t  *conf;
+    int                           last;
+    off_t                         size, flush, sent;
+    ngx_chain_t                  *cl, *ln, **ll, *chain;
+    ngx_http_core_loc_conf_t     *clcf;
+    ngx_http_write_filter_ctx_t  *ctx;
 
     ctx = ngx_http_get_module_ctx(r->main ? r->main : r,
                                   ngx_http_write_filter_module);
@@ -125,8 +96,8 @@ ngx_int_t ngx_http_write_filter(ngx_http
                    "http write filter: l:%d f:" OFF_T_FMT " s:" OFF_T_FMT,
                    last, flush, size);
 
-    conf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
-                                        ngx_http_write_filter_module);
+    clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
+                                        ngx_http_core_module);
 
     /*
      * avoid the output if there is no last buf, no flush point,
@@ -134,7 +105,7 @@ ngx_int_t ngx_http_write_filter(ngx_http
      * is smaller than "postpone_output" directive
      */
 
-    if (!last && flush == 0 && in && size < (off_t) conf->postpone_output) {
+    if (!last && flush == 0 && in && size < (off_t) clcf->postpone_output) {
         return NGX_OK;
     }
 
@@ -153,17 +124,17 @@ ngx_int_t ngx_http_write_filter(ngx_http
     sent = r->connection->sent;
 
     chain = ngx_write_chain(r->connection, ctx->out,
-                            conf->limit_rate ? conf->limit_rate:
+                            clcf->limit_rate ? clcf->limit_rate:
                                                OFF_T_MAX_VALUE);
 
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http write filter %X", chain);
 
-    if (conf->limit_rate) {
+    if (clcf->limit_rate) {
         sent = r->connection->sent - sent;
         r->connection->write->delayed = 1;
         ngx_add_timer(r->connection->write,
-                      (ngx_msec_t) sent * 1000 / conf->limit_rate);
+                      (ngx_msec_t) (sent * 1000 / clcf->limit_rate));
     }
 
     if (chain == NGX_CHAIN_ERROR) {
@@ -180,36 +151,6 @@ ngx_int_t ngx_http_write_filter(ngx_http
 }
 
 
-static void *ngx_http_write_filter_create_conf(ngx_conf_t *cf)
-{
-    ngx_http_write_filter_conf_t *conf;
-
-    ngx_test_null(conf,
-                  ngx_palloc(cf->pool, sizeof(ngx_http_write_filter_conf_t)),
-                  NULL);
-
-    conf->postpone_output = NGX_CONF_UNSET_SIZE;
-    conf->limit_rate = NGX_CONF_UNSET_SIZE;
-
-    return conf;
-}
-
-
-static char *ngx_http_write_filter_merge_conf(ngx_conf_t *cf,
-                                              void *parent, void *child)
-{
-    ngx_http_write_filter_conf_t *prev = parent;
-    ngx_http_write_filter_conf_t *conf = child;
-
-    ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output,
-                              1460);
-
-    ngx_conf_merge_size_value(conf->limit_rate, prev->limit_rate, 0);
-
-    return NULL;
-}
-
-
 static ngx_int_t ngx_http_write_filter_init(ngx_cycle_t *cycle)
 {
     ngx_http_top_body_filter = ngx_http_write_filter;
--- a/src/os/unix/ngx_channel.c
+++ b/src/os/unix/ngx_channel.c
@@ -205,7 +205,7 @@ ngx_int_t ngx_add_channel_event(ngx_cycl
 
     ev->event_handler = handler;
 
-    if (ngx_add_conn) {
+    if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
         if (ngx_add_conn(c) == NGX_ERROR) {
             return NGX_ERROR;
         }
@@ -218,3 +218,15 @@ ngx_int_t ngx_add_channel_event(ngx_cycl
 
     return NGX_OK;
 }
+
+
+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() failed");
+    }
+
+    if (close(fd[1]) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "close() failed");
+    }
+}
--- a/src/os/unix/ngx_channel.h
+++ b/src/os/unix/ngx_channel.h
@@ -21,6 +21,7 @@ ngx_int_t ngx_read_channel(ngx_socket_t 
                            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);
+void ngx_close_channel(ngx_fd_t *fd, ngx_log_t *log);
 
 
 #endif /* _NGX_CHANNEL_H_INCLUDED_ */
--- a/src/os/unix/ngx_freebsd_init.c
+++ b/src/os/unix/ngx_freebsd_init.c
@@ -84,7 +84,7 @@ int ngx_os_init(ngx_log_t *log)
     size = sizeof(ngx_freebsd_kern_ostype);
     if (sysctlbyname("kern.ostype",
                      ngx_freebsd_kern_ostype, &size, NULL, 0) == -1) {
-        ngx_log_error(NGX_LOG_ALERT, log, errno,
+        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
                       "sysctlbyname(kern.ostype) failed");
         return NGX_ERROR;
     }
@@ -92,7 +92,7 @@ int ngx_os_init(ngx_log_t *log)
     size = sizeof(ngx_freebsd_kern_osrelease);
     if (sysctlbyname("kern.osrelease",
                      ngx_freebsd_kern_osrelease, &size, NULL, 0) == -1) {
-        ngx_log_error(NGX_LOG_ALERT, log, errno,
+        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
                       "sysctlbyname(kern.osrelease) failed");
         return NGX_ERROR;
     }
@@ -104,7 +104,7 @@ int ngx_os_init(ngx_log_t *log)
     size = sizeof(int);
     if (sysctlbyname("kern.osreldate",
                      &ngx_freebsd_kern_osreldate, &size, NULL, 0) == -1) {
-        ngx_log_error(NGX_LOG_ALERT, log, errno,
+        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
                       "sysctlbyname(kern.osreldate) failed");
         return NGX_ERROR;
     }
@@ -169,7 +169,7 @@ int ngx_os_init(ngx_log_t *log)
         size = sysctls[i].size;
         if (sysctlbyname(sysctls[i].name, sysctls[i].value, &size, NULL, 0)
                                                                        == -1) {
-            err = errno;
+            err = ngx_errno;
             if (err != NGX_ENOENT) {
                 if (sysctls[i].value == &ngx_freebsd_machdep_hlt_logical_cpus) {
                     continue;
--- a/src/os/unix/ngx_linux.h
+++ b/src/os/unix/ngx_linux.h
@@ -5,5 +5,7 @@
 ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in,
                                       off_t limit);
 
+extern int ngx_linux_rtsig_max;
+
 
 #endif /* _NGX_LINUX_H_INCLUDED_ */
--- a/src/os/unix/ngx_linux_init.c
+++ b/src/os/unix/ngx_linux_init.c
@@ -6,6 +6,8 @@
 char ngx_linux_kern_ostype[50];
 char ngx_linux_kern_osrelease[20];
 
+int ngx_linux_rtsig_max;
+
 
 ngx_os_io_t ngx_os_io = {
     ngx_unix_recv,
@@ -23,14 +25,15 @@ ngx_os_io_t ngx_os_io = {
 
 int ngx_os_init(ngx_log_t *log)
 {
-    int  name[2], len;
+    int  name[2], len, rtsig_max;
 
     name[0] = CTL_KERN;
     name[1] = KERN_OSTYPE;
     len = sizeof(ngx_linux_kern_ostype);
     if (sysctl(name, sizeof(name), ngx_linux_kern_ostype, &len, NULL, 0)
                                                                        == -1) {
-        ngx_log_error(NGX_LOG_ALERT, log, errno, "sysctl(KERN_OSTYPE) failed");
+        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+                      "sysctl(KERN_OSTYPE) failed");
         return NGX_ERROR;
     }
 
@@ -39,7 +42,7 @@ int ngx_os_init(ngx_log_t *log)
     len = sizeof(ngx_linux_kern_osrelease);
     if (sysctl(name, sizeof(name), ngx_linux_kern_osrelease, &len, NULL, 0)
                                                                        == -1) {
-        ngx_log_error(NGX_LOG_ALERT, log, errno,
+        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
                       "sysctl(KERN_OSRELEASE) failed");
         return NGX_ERROR;
     }
@@ -48,5 +51,16 @@ int ngx_os_init(ngx_log_t *log)
                   ngx_linux_kern_ostype, ngx_linux_kern_osrelease);
 
 
+    name[0] = CTL_KERN;
+    name[1] = KERN_RTSIGMAX;
+    len = sizeof(rtsig_max);
+    if (sysctl(name, sizeof(name), &rtsig_max, &len, NULL, 0) == -1) {
+        ngx_log_error(NGX_LOG_INFO, log, ngx_errno,
+                      "sysctl(KERN_RTSIGMAX) failed");
+    } else {
+        ngx_linux_rtsig_max = 1;
+    }
+
+
     return ngx_posix_init(log);
 }
--- a/src/os/unix/ngx_process.c
+++ b/src/os/unix/ngx_process.c
@@ -2,6 +2,7 @@
 #include <ngx_config.h>
 #include <ngx_core.h>
 #include <ngx_event.h>
+#include <ngx_channel.h>
 
 
 static void ngx_execute_proc(ngx_cycle_t *cycle, void *data);
@@ -50,6 +51,11 @@ ngx_pid_t ngx_spawn_process(ngx_cycle_t 
             return NGX_ERROR;
         }
 
+        ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
+                       "channel %d:%d",
+                       ngx_processes[s].channel[0],
+                       ngx_processes[s].channel[1]);
+
         if (ngx_nonblocking(ngx_processes[s].channel[0]) == -1) {
             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                           ngx_nonblocking_n " failed while spawning \"%s\"",
@@ -270,15 +276,3 @@ void ngx_process_get_status()
         }
     }
 }
-
-
-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() failed");
-    } 
-
-    if (close(fd[1]) == -1) {
-        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "close() failed");
-    } 
-}
--- a/src/os/unix/ngx_process.h
+++ b/src/os/unix/ngx_process.h
@@ -47,7 +47,6 @@ ngx_pid_t ngx_spawn_process(ngx_cycle_t 
                             char *name, ngx_int_t respawn);
 ngx_pid_t ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx);
 void ngx_process_get_status(void);
-void ngx_close_channel(ngx_fd_t *fd, ngx_log_t *log);
 
 #define ngx_sched_yield()  sched_yield()
 
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -614,6 +614,10 @@ static void ngx_worker_process_cycle(ngx
             continue;
         }
 
+        if (n == ngx_process_slot) {
+            continue;
+        }
+
         if (close(ngx_processes[n].channel[1]) == -1) {
             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                           "close() failed");
--- a/src/os/unix/ngx_pthread_thread.c
+++ b/src/os/unix/ngx_pthread_thread.c
@@ -146,6 +146,10 @@ ngx_int_t ngx_mutex_trylock(ngx_mutex_t 
 
     err = pthread_mutex_trylock(&m->mutex);
 
+    if (err == NGX_EBUSY) {
+        return NGX_AGAIN;
+    }
+
     if (err != 0) {
         ngx_log_error(NGX_LOG_ALERT, m->log, err,
                       "pthread_mutex_trylock(" PTR_FMT ") failed", m);
--- a/src/os/unix/ngx_solaris_init.c
+++ b/src/os/unix/ngx_solaris_init.c
@@ -27,21 +27,24 @@ int ngx_os_init(ngx_log_t *log)
     if (sysinfo(SI_SYSNAME, ngx_solaris_sysname, sizeof(ngx_solaris_sysname))
                                                                          == -1)
     {
-        ngx_log_error(NGX_LOG_ALERT, log, errno, "sysinfo(SI_SYSNAME) failed");
+        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+                      "sysinfo(SI_SYSNAME) failed");
         return NGX_ERROR;
     }
 
     if (sysinfo(SI_RELEASE, ngx_solaris_release, sizeof(ngx_solaris_release))
                                                                          == -1)
     {
-        ngx_log_error(NGX_LOG_ALERT, log, errno, "sysinfo(SI_RELEASE) failed");
+        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+                      "sysinfo(SI_RELEASE) failed");
         return NGX_ERROR;
     }
 
     if (sysinfo(SI_VERSION, ngx_solaris_version, sizeof(ngx_solaris_version))
                                                                          == -1)
     {
-        ngx_log_error(NGX_LOG_ALERT, log, errno, "sysinfo(SI_SYSNAME) failed");
+        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+                      "sysinfo(SI_SYSNAME) failed");
         return NGX_ERROR;
     }