nginx-0.0.1-2004-01-05-23:55:48 import
diff --git a/src/os/unix/ngx_errno.h b/src/os/unix/ngx_errno.h
index bead5f9..1542456 100644
--- a/src/os/unix/ngx_errno.h
+++ b/src/os/unix/ngx_errno.h
@@ -20,6 +20,7 @@
 #define NGX_EINPROGRESS   EINPROGRESS
 #define NGX_EADDRINUSE    EADDRINUSE
 #define NGX_ECONNRESET    ECONNRESET
+#define NGX_ENOTCONN      ENOTCONN
 #define NGX_ETIMEDOUT     ETIMEDOUT
 #define NGX_ECANCELED     ECANCELED
 #define NGX_ENOMOREFILES  0
diff --git a/src/os/unix/ngx_freebsd_config.h b/src/os/unix/ngx_freebsd_config.h
index 04524b4..ce5c3b6 100644
--- a/src/os/unix/ngx_freebsd_config.h
+++ b/src/os/unix/ngx_freebsd_config.h
@@ -24,6 +24,7 @@
 #include <dirent.h>
 #include <arpa/inet.h>
 #include <netdb.h>
+#include <pwd.h>
 #include <osreldate.h>
 
 
diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c
index 63c877f..16aa2ad 100644
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -151,7 +151,7 @@
 
         if (file) {
 
-            if (ngx_freebsd_use_tcp_nopush && !c->tcp_nopush) {
+            if (ngx_freebsd_use_tcp_nopush && c->tcp_nopush == 0) {
                 c->tcp_nopush = 1;
 
                 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "tcp_nopush");
@@ -191,7 +191,7 @@
                 } else if (err == NGX_EAGAIN) {
                     eagain = 1;
 
-                } else if (err == NGX_EPIPE) {
+                } else if (err == NGX_EPIPE || err == NGX_ENOTCONN) {
                     level = NGX_LOG_INFO;
                 }
 
@@ -202,8 +202,13 @@
 
                 } else {
                     wev->error = 1;
+#if 0
                     ngx_log_error(level, c->log, err,
                                   "sendfile() failed");
+#else
+                    ngx_log_error(level, c->log, err,
+                                  "sendfile(#%d) failed", c->fd);
+#endif
                     return NGX_CHAIN_ERROR;
                 }
             }
diff --git a/src/os/unix/ngx_linux_sendfile_chain.c b/src/os/unix/ngx_linux_sendfile_chain.c
index d4e45bb..5fc61f0 100644
--- a/src/os/unix/ngx_linux_sendfile_chain.c
+++ b/src/os/unix/ngx_linux_sendfile_chain.c
@@ -6,7 +6,7 @@
 
 /*
  * On Linux up to 2.4.21 sendfile() (syscall #187) works with 32-bit
- * offsets only and the including <sys/sendfile.h> breaks building if
+ * offsets only and the including <sys/sendfile.h> breaks the compiling if
  * off_t is 64 bit wide.  So we use own sendfile() definition where offset
  * parameter is int32_t and use sendfile() with the file parts below 2G.
  *
@@ -75,14 +75,14 @@
 
         /* set TCP_CORK if there is a header before a file */
 
-        if (!c->tcp_nopush
+        if (!c->tcp_nopush == 0
             && header.nelts != 0
             && cl
             && cl->hunk->type & NGX_HUNK_FILE)
         {
             c->tcp_nopush = 1;
 
-ngx_log_debug(c->log, "CORK");
+            ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "tcp_nopush");
 
             if (ngx_tcp_nopush(c->fd) == NGX_ERROR) {
                 ngx_log_error(NGX_LOG_CRIT, c->log, ngx_errno,
diff --git a/src/os/unix/ngx_os.h b/src/os/unix/ngx_os.h
index cc693fa..ed6b695 100644
--- a/src/os/unix/ngx_os.h
+++ b/src/os/unix/ngx_os.h
@@ -49,9 +49,13 @@
 extern int          ngx_inherited_nonblocking;
 
 
-extern int          done;
-extern int          restart;
-extern int          rotate;
+extern ngx_int_t    ngx_master;
+
+extern ngx_int_t    ngx_quit;
+extern ngx_int_t    ngx_terminate;
+extern ngx_int_t    ngx_reconfigure;
+extern ngx_int_t    ngx_reopen;
+extern ngx_int_t    ngx_change_binary;
 
 
 #ifdef __FreeBSD__
diff --git a/src/os/unix/ngx_posix_init.c b/src/os/unix/ngx_posix_init.c
index 5ae5c73..d46a65d 100644
--- a/src/os/unix/ngx_posix_init.c
+++ b/src/os/unix/ngx_posix_init.c
@@ -8,9 +8,6 @@
 
 
 void ngx_signal_handler(int signo);
-void ngx_exit_signal_handler(int signo);
-void ngx_restart_signal_handler(int signo);
-void ngx_rotate_signal_handler(int signo);
 
 
 typedef struct {
@@ -22,27 +19,37 @@
 
 
 ngx_signal_t  signals[] = {
-    { ngx_signal_value(NGX_RESTART_SIGNAL),
-      "SIG" ngx_value(NGX_RESTART_SIGNAL),
-      "restarting",
+    { ngx_signal_value(NGX_RECONFIGURE_SIGNAL),
+      "SIG" ngx_value(NGX_RECONFIGURE_SIGNAL),
+      ", reconfiguring",
       ngx_signal_handler },
 
-    { ngx_signal_value(NGX_ROTATE_SIGNAL),
-      "SIG" ngx_value(NGX_ROTATE_SIGNAL),
-      "reopen logs",
+    { ngx_signal_value(NGX_REOPEN_SIGNAL),
+      "SIG" ngx_value(NGX_REOPEN_SIGNAL),
+      ", reopen logs",
       ngx_signal_handler },
 
     { ngx_signal_value(NGX_INTERRUPT_SIGNAL),
       "SIG" ngx_value(NGX_INTERRUPT_SIGNAL),
-      "exiting",
+      ", exiting",
+      ngx_signal_handler },
+
+    { ngx_signal_value(NGX_TERMINATE_SIGNAL),
+      "SIG" ngx_value(NGX_TERMINATE_SIGNAL),
+      ", exiting",
       ngx_signal_handler },
 
     { ngx_signal_value(NGX_SHUTDOWN_SIGNAL),
       "SIG" ngx_value(NGX_SHUTDOWN_SIGNAL),
-      "shutdowning",
+      ", shutdowning",
       ngx_signal_handler },
 
-    { SIGCHLD, "SIGCHLD", NULL, ngx_sigchld_handler },
+    { ngx_signal_value(NGX_CHANGEBIN_SIGNAL),
+      "SIG" ngx_value(NGX_CHANGEBIN_SIGNAL),
+      ", changing binary",
+      ngx_signal_handler },
+
+    { SIGCHLD, "SIGCHLD", "", ngx_signal_handler },
 
     { SIGPIPE, "SIGPIPE, SIG_IGN", NULL, SIG_IGN },
 
@@ -91,7 +98,8 @@
 
 void ngx_signal_handler(int signo)
 {
-    ngx_signal_t  *sig;
+    struct timeval   tv;
+    ngx_signal_t    *sig;
 
     for (sig = signals; sig->signo != 0; sig++) {
         if (sig->signo == signo) {
@@ -99,64 +107,43 @@
         }
     }
 
-#if (HAVE_STRSIGNAL)
+    ngx_gettimeofday(&tv);
+    ngx_time_update(tv.tv_sec);
 
     ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
-                  "signal #%d (%s: %s) received, %s",
-                  signo, sig->signame, strsignal(signo), sig->action);
-#else
-
-    ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
-                  "signal #%d (%s) received, %s",
+                  "signal %d (%s) received%s",
                   signo, sig->signame, sig->action);
 
-#endif
-
     switch (signo) {
 
-    /* STUB */
-    case SIGQUIT:
-    case SIGABRT:
+    case SIGCHLD:
+        ngx_process_get_status();
+        break;
 
     case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
+        ngx_quit = 1;
+        break;
+
+    case ngx_signal_value(NGX_TERMINATE_SIGNAL):
     case ngx_signal_value(NGX_INTERRUPT_SIGNAL):
-        done = 1;
+        ngx_terminate = 1;
         break;
 
-    case ngx_signal_value(NGX_RESTART_SIGNAL):
-        restart = 1;
+    case ngx_signal_value(NGX_RECONFIGURE_SIGNAL):
+        ngx_reconfigure = 1;
         break;
 
-    case ngx_signal_value(NGX_ROTATE_SIGNAL):
-        rotate = 1;
+    case ngx_signal_value(NGX_REOPEN_SIGNAL):
+        ngx_reopen = 1;
+        break;
+
+    case ngx_signal_value(NGX_CHANGEBIN_SIGNAL):
+        ngx_change_binary = 1;
         break;
     }
 }
 
 
-void ngx_exit_signal_handler(int signo)
-{
-    char *s;
-
-    s = strsignal(signo);
-    ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
-                  "%s signal received, exiting", s);
-    done = 1;
-}
-
-
-void ngx_restart_signal_handler(int signo)
-{
-    restart = 1;
-}
-
-
-void ngx_rotate_signal_handler(int signo)
-{
-    rotate = 1;
-}
-
-
 int ngx_posix_post_conf_init(ngx_log_t *log)
 {
     ngx_fd_t  pp[2];
diff --git a/src/os/unix/ngx_process.c b/src/os/unix/ngx_process.c
index 04e2475..f7314a4 100644
--- a/src/os/unix/ngx_process.c
+++ b/src/os/unix/ngx_process.c
@@ -3,73 +3,241 @@
 #include <ngx_core.h>
 
 
-void testone(ngx_log_t *log)
+static void ngx_exec_proc(ngx_cycle_t *cycle, void *data);
+
+ngx_uint_t     ngx_last_process;
+ngx_process_t  ngx_processes[NGX_MAX_PROCESSES];
+
+
+ngx_int_t ngx_spawn_process(ngx_cycle_t *cycle,
+                            ngx_spawn_proc_pt proc, void *data,
+                            char *name, ngx_int_t respawn)
 {
-    ngx_log_debug(log, "child process");
-    ngx_msleep(5000);
-    exit(0);
-}
+    sigset_t   set, oset;
+    ngx_pid_t  pid;
 
-
-int ngx_spawn_process(ngx_log_t *log)
-{
-    pid_t     pid;
-    sigset_t  set, oset; 
-
-    sigemptyset(&set);
-    sigaddset(&set, SIGCHLD);
-    if (sigprocmask(SIG_BLOCK, &set, &oset) == -1) {
-        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "sigprocmask() failed");
+    if (respawn < 0) {
+        sigemptyset(&set);
+        sigaddset(&set, SIGCHLD);
+        if (sigprocmask(SIG_BLOCK, &set, &oset) == -1) {
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                          "sigprocmask() failed while spawning %s", name);
+            return NGX_ERROR;
+        }
     }
 
     pid = fork();
 
+    if (pid == -1) {
+        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                      "fork() failed while spawning \"%s\"", name);
+    }
+
     if (pid == -1 || pid == 0) {
         if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) {
-            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
-                          "sigprocmask() failed");
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                          "sigprocmask() failed while spawning %s", name);
+            return NGX_ERROR;
         }
     }
 
     switch (pid) {
     case -1:
-        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "fork() failed");
         return NGX_ERROR;
 
     case 0:
-        testone(log);
+        proc(cycle, data);
         break;
 
     default:
         break;
     }
 
-ngx_log_debug(log, "parent process, child: " PID_T_FMT _ pid);
+    ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
+                   "spawn %s: " PID_T_FMT, name, pid);
 
-    /* book keeping */
+    if (respawn >= 0) {
+        ngx_processes[respawn].pid = pid;
+        ngx_processes[respawn].exited = 0;
+        return NGX_OK;
+    }
+
+    ngx_processes[ngx_last_process].pid = pid;
+    ngx_processes[ngx_last_process].proc = proc;
+    ngx_processes[ngx_last_process].data = data;
+    ngx_processes[ngx_last_process].name = name;
+    ngx_processes[ngx_last_process].respawn =
+                                      (respawn == NGX_PROCESS_RESPAWN) ? 1 : 0;
+    ngx_processes[ngx_last_process].detached =
+                                     (respawn == NGX_PROCESS_DETACHED) ? 1 : 0;
+    ngx_processes[ngx_last_process].exited = 0;
+    ngx_processes[ngx_last_process].exiting = 0;
+    ngx_last_process++;
 
     if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) {
-        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "sigprocmask() failed");
+        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                      "sigprocmask() failed while spawning %s", name);
+        return NGX_ERROR;
     }
 
     return NGX_OK;
 }
 
 
-void ngx_sigchld_handler(int signo)
+ngx_int_t ngx_exec(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx)
 {
-    int             status, one;
-    pid_t           pid;
-    ngx_err_t       err;
-    struct timeval  tv;
-
-    ngx_gettimeofday(&tv);
-
-    if (ngx_cached_time != tv.tv_sec) {
-        ngx_cached_time = tv.tv_sec;
-        ngx_time_update();
+    if (ngx_spawn_process(cycle, ngx_exec_proc, ctx, ctx->name,
+                                            NGX_PROCESS_DETACHED) == NGX_ERROR)
+    {
+        ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
+                      "can not spawn %s", ctx->name);
+        return NGX_ERROR;
     }
 
+    return NGX_OK;
+}
+
+
+static void ngx_exec_proc(ngx_cycle_t *cycle, void *data)
+{
+    ngx_exec_ctx_t  *ctx = data;
+
+    if (execve(ctx->path, ctx->argv, ctx->envp) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                      "execve() failed while executing %s \"%s\"",
+                      ctx->name, ctx->path);
+    }
+
+    exit(1);
+}
+
+
+void ngx_signal_processes(ngx_cycle_t *cycle, ngx_int_t signal)
+{
+    sigset_t    set, oset;
+    ngx_uint_t  i;
+
+    sigemptyset(&set);
+    sigaddset(&set, SIGCHLD);
+    if (sigprocmask(SIG_BLOCK, &set, &oset) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                      "sigprocmask() failed while signaling processes");
+        return;
+    }
+
+    for (i = 0; i < ngx_last_process; i++) {
+
+        if (ngx_processes[i].detached) {
+            continue;
+        }
+
+        if (ngx_processes[i].exited) {
+            if (i != --ngx_last_process) {
+                ngx_processes[i--] = ngx_processes[ngx_last_process];
+            }
+            continue;
+        }
+
+        ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
+                       "kill (" PID_T_FMT ", %d)" ,
+                       ngx_processes[i].pid, signal);
+
+        if (kill(ngx_processes[i].pid, signal) == -1) {
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                          "kill(%d, %d) failed", ngx_processes[i].pid, signal);
+            continue;
+        }
+
+        if (signal != ngx_signal_value(NGX_REOPEN_SIGNAL)) {
+            ngx_processes[i].exiting = 1;
+        }
+    }
+
+    if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                      "sigprocmask() failed while signaling processes");
+    }
+}
+
+
+void ngx_respawn_processes(ngx_cycle_t *cycle)
+{
+    sigset_t    set, oset;
+    ngx_uint_t  i;
+
+    sigemptyset(&set);
+    sigaddset(&set, SIGCHLD);
+    if (sigprocmask(SIG_BLOCK, &set, &oset) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                      "sigprocmask() failed while respawning processes");
+        return;
+    }
+
+    /*
+     * to avoid a race condition we can check and set value of ngx_respawn
+     * only in signal handler or while SIGCHLD is blocked
+     */
+
+    if (ngx_respawn) {
+
+        for (i = 0; i < ngx_last_process; i++) {
+            if (!ngx_processes[i].exited) {
+                continue;
+            }
+
+            if (!ngx_processes[i].respawn) {
+                if (i != --ngx_last_process) {
+                    ngx_processes[i--] = ngx_processes[ngx_last_process];
+                }
+                continue;
+            }
+
+            if (ngx_spawn_process(cycle,
+                                  ngx_processes[i].proc, ngx_processes[i].data,
+                                  ngx_processes[i].name, i) == NGX_ERROR)
+            {
+                ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
+                              "can not respawn %s", ngx_processes[i].name);
+            }
+        }
+
+        ngx_respawn = 0;
+    }
+
+    if (sigprocmask(SIG_SETMASK, &oset, &set) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                      "sigprocmask() failed while respawning processes");
+    }
+}
+
+
+#if 0
+void ngx_sigchld_handler(int signo)
+{
+    int              status;
+    char            *process;
+    ngx_pid_t        pid;
+    ngx_err_t        err;
+    ngx_uint_t       i, one;
+    struct timeval   tv;
+
+    ngx_gettimeofday(&tv);
+    ngx_time_update(tv.tv_sec);
+
+    ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
+                  "signal #%d (SIGCHLD) received", signo);
+}
+#endif
+
+
+void ngx_process_get_status()
+{
+    int              status;
+    char            *process;
+    ngx_pid_t        pid;
+    ngx_err_t        err;
+    ngx_uint_t       i, one;
+    struct timeval   tv;
     one = 0;
 
     for ( ;; ) {
@@ -96,18 +264,39 @@
         }
 
         one = 1;
+        process = "";
 
-        ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
-                      "process " PID_T_FMT " exited with code %d", pid, status);
+        for (i = 0; i < ngx_last_process; i++) {
+            if (ngx_processes[i].pid == pid) {
+                ngx_processes[i].status = status;
 
-        /* TODO: restart handler */
+                if (!ngx_processes[i].exiting) {
+                    ngx_processes[i].exited = 1;
 
-#if 0
-        ngx_msleep(2000);
-#endif
+                    if (ngx_processes[i].respawn) {
+                        ngx_respawn = 1;
+                    }
+                }
 
-#if 0
-        ngx_spawn_process(ngx_cycle->log);
-#endif
+                process = ngx_processes[i].name;
+                break;
+            }
+        }
+
+        if (i == ngx_last_process) {
+            process = "unknown process";
+        }
+
+        if (WTERMSIG(status)) {
+            ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
+                          "%s " PID_T_FMT " exited on signal %d%s",
+                          process, pid, WTERMSIG(status),
+                          WCOREDUMP(status) ? " (core dumped)" : "");
+
+        } else {
+            ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
+                          "%s " PID_T_FMT " exited with code %d",
+                          process, pid, WEXITSTATUS(status));
+        }
     }
 }
diff --git a/src/os/unix/ngx_process.h b/src/os/unix/ngx_process.h
index 15d9c0d..5b7e37c 100644
--- a/src/os/unix/ngx_process.h
+++ b/src/os/unix/ngx_process.h
@@ -4,11 +4,51 @@
 
 typedef pid_t       ngx_pid_t;
 
+typedef void (*ngx_spawn_proc_pt) (ngx_cycle_t *cycle, void *data);
+
+typedef struct {
+    ngx_pid_t           pid;
+    int                 status;
+
+    ngx_spawn_proc_pt   proc;
+    void               *data;
+    char               *name;
+
+    unsigned            respawn:1;
+    unsigned            detached:1;
+    unsigned            exited:1;
+    unsigned            exiting:1;
+} ngx_process_t;
+
+
+typedef struct {
+    char         *path;
+    char         *name;
+    char *const  *argv;
+    char *const  *envp;
+} ngx_exec_ctx_t;
+
+
 #define ngx_getpid  getpid
 
+#define NGX_MAX_PROCESSES  1024
 
-int ngx_spawn_process(ngx_log_t *log);
-void ngx_sigchld_handler(int signo);
+#define NGX_PROCESS_RESPAWN    -1
+#define NGX_PROCESS_NORESPAWN  -2
+#define NGX_PROCESS_DETACHED   -3
+
+
+ngx_int_t ngx_spawn_process(ngx_cycle_t *cycle,
+                            ngx_spawn_proc_pt proc, void *data,
+                            char *name, ngx_int_t respawn);
+ngx_int_t ngx_exec(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx);
+void ngx_signal_processes(ngx_cycle_t *cycle, ngx_int_t signal);
+void ngx_respawn_processes(ngx_cycle_t *cycle);
+void ngx_process_get_status(void);
+
+extern ngx_int_t      ngx_respawn;
+extern ngx_uint_t     ngx_last_process;
+extern ngx_process_t  ngx_processes[NGX_MAX_PROCESSES];
 
 
 #endif /* _NGX_PROCESS_H_INCLUDED_ */
diff --git a/src/os/unix/ngx_recv.c b/src/os/unix/ngx_recv.c
index 7cb949a..1ebbe69 100644
--- a/src/os/unix/ngx_recv.c
+++ b/src/os/unix/ngx_recv.c
@@ -17,8 +17,9 @@
     rev = c->read;
 
     if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
-        ngx_log_debug(c->log, "recv: eof:%d, avail:%d, err:%d" _
-                      rev->kq_eof _ rev->available _ rev->kq_errno);
+        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                       "recv: eof:%d, avail:%d, err:%d",
+                       rev->kq_eof, rev->available, rev->kq_errno);
 
         if (rev->available == 0) {
             if (rev->kq_eof) {
@@ -28,7 +29,16 @@
                 if (rev->kq_errno) {
                     rev->error = 1;
                     ngx_set_socket_errno(rev->kq_errno);
-                    return ngx_unix_recv_error(rev, rev->kq_errno);
+                    ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
+                                  "kevent() reported about closed connection");
+
+                    if (rev->kq_errno == NGX_ECONNRESET
+                        && rev->log_error == NGX_ERROR_IGNORE_ECONNRESET)
+                    {
+                        return 0;
+                    }
+
+                    return NGX_ERROR;
                 }
 
                 return 0;
@@ -42,7 +52,7 @@
     do {
         n = recv(c->fd, buf, size, 0);
 
-        ngx_log_debug(c->log, "recv: %d:%d" _ n _ size);
+        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,"recv: %d:%d", n, size);
 
         if (n >= 0) {
             if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
@@ -104,7 +114,7 @@
     do {
         n = recv(c->fd, buf, size, 0);
 
-        ngx_log_debug(c->log, "recv: %d:%d" _ n _ size);
+        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,"recv: %d:%d", n, size);
 
         if (n >= 0) {
             if ((size_t) n < size) {
@@ -138,21 +148,33 @@
 
 static int ngx_unix_recv_error(ngx_event_t *rev, ngx_err_t err)
 {
-    if (err == NGX_ECONNRESET && rev->ignore_econnreset) {
-        return 0;
-    }
+    ngx_int_t  level;
 
-    if (err == NGX_EAGAIN) {
-        ngx_log_error(NGX_LOG_INFO, rev->log, err, "recv() returned EAGAIN");
+    if (err == NGX_EAGAIN || err == NGX_EINTR) {
+        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, rev->log, err, "recv() not ready");
         return NGX_AGAIN;
     }
 
-    if (err == NGX_EINTR) {
-        ngx_log_error(NGX_LOG_INFO, rev->log, err, "recv() returned EINTR");
-        return NGX_EINTR;
+    if (err == NGX_ECONNRESET) {
+
+        switch (rev->log_error) {
+        case NGX_ERROR_IGNORE_ECONNRESET:
+            return 0;
+        case NGX_ERROR_INFO:
+            level = NGX_LOG_INFO;
+            break;
+        case NGX_ERROR_ERR:
+            level = NGX_LOG_ERR;
+            break;
+        default:
+            level = NGX_LOG_CRIT;
+        }
+
+    } else {
+        level = NGX_LOG_CRIT;
     }
 
-    ngx_log_error(NGX_LOG_ERR, rev->log, err, "recv() failed");
+    ngx_log_error(level, rev->log, err, "recv() failed");
 
     return NGX_ERROR;
 }