nginx-0.0.2-2004-02-09-10:46:43 import
diff --git a/src/os/unix/ngx_freebsd_init.c b/src/os/unix/ngx_freebsd_init.c
index 2056179..0f02fba 100644
--- a/src/os/unix/ngx_freebsd_init.c
+++ b/src/os/unix/ngx_freebsd_init.c
@@ -115,8 +115,8 @@
 
     /*
      * The determination of the sendfile() nbytes bug is complex enough.
-     * There are two sendfile() syscalls: a new 393 has no bug while
-     * an old 336 has the bug in some versions and has not in others.
+     * There are two sendfile() syscalls: a new #393 has no bug while
+     * an old #336 has the bug in some versions and has not in others.
      * Besides libc_r wrapper also emulates the bug in some versions.
      * There's no way to say exactly if a given FreeBSD version has the bug.
      * Here is the algorithm that works at least for RELEASEs
diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c
index 16aa2ad..f784b1f 100644
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -5,17 +5,20 @@
 
 
 /*
- * FreeBSD's sendfile() often sends 4K pages over ethernet in 3 packets: 2x1460
- * and 1176 or in 6 packets: 5x1460 and 892.  Besides although sendfile()
- * allows to pass the header and the trailer it never sends the header or
- * the trailer with the part of the file in one packet.  So we use TCP_NOPUSH
- * (similar to Linux's TCP_CORK) to postpone the sending - it not only sends
- * the header and the first part of the file in one packet but also sends
- * 4K pages in the full packets.
+ * Although FreeBSD sendfile() allows to pass a header and a trailer
+ * it never sends a header with a part of the file in one packet until
+ * FreeBSD 5.2-STABLE.  Besides over the fast ethernet connection sendfile()
+ * can send the partially filled packets, i.e. the 8 file pages can be sent
+ * as 11 full 1460-bytes packets, then one incomplete 324-bytes packet, and
+ * then again 11 full 1460-bytes packets.
  *
- * Until FreeBSD 4.5 the turning TCP_NOPUSH off does not flush a pending
+ * So we use the TCP_NOPUSH option (similar to Linux's TCP_CORK)
+ * to postpone the sending - it not only sends a header and the first part
+ * of the file in one packet but also sends file pages in the full packets.
+ *
+ * But until FreeBSD 4.5 the turning TCP_NOPUSH off does not flush a pending
  * data that less than MSS so that data can be sent with 5 second delay.
- * We do not use TCP_NOPUSH on FreeBSD prior to 4.5 although it can be used
+ * So we do not use TCP_NOPUSH on FreeBSD prior to 4.5 although it can be used
  * for non-keepalive HTTP connections.
  */
 
@@ -26,7 +29,7 @@
     char            *prev;
     off_t            sent, fprev;
     size_t           hsize, fsize, size;
-    ngx_int_t        eintr, eagain, level;
+    ngx_int_t        eintr, eagain;
     struct iovec    *iov;
     struct sf_hdtr   hdtr;
     ngx_err_t        err;
@@ -45,7 +48,7 @@
 
     if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) && wev->kq_eof) {
         ngx_log_error(NGX_LOG_INFO, c->log, wev->kq_errno,
-                      "kevent() reported about closed connection");
+                      "kevent() reported about an closed connection");
 
         wev->error = 1;
         return NGX_CHAIN_ERROR;
@@ -59,7 +62,6 @@
         hsize = 0;
         eintr = 0;
         eagain = 0;
-        level = NGX_LOG_CRIT;
 
         ngx_init_array(header, c->pool, 10, sizeof(struct iovec),
                        NGX_CHAIN_ERROR);
@@ -152,14 +154,26 @@
         if (file) {
 
             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");
 
                 if (ngx_tcp_nopush(c->fd) == NGX_ERROR) {
-                    ngx_log_error(NGX_LOG_CRIT, c->log, ngx_errno,
-                                  ngx_tcp_nopush_n " failed");
-                    return NGX_CHAIN_ERROR;
+                    err = ngx_errno;
+
+                    /*
+                     * there is a tiny chance to be interrupted, however
+                     * we continue a processing without the TCP_NOPUSH
+                     */
+
+                    if (err != NGX_EINTR) {
+                        wev->error = 1;
+                        ngx_connection_error(c, err,
+                                             ngx_tcp_nopush_n " failed");
+                        return NGX_CHAIN_ERROR;
+                    }
+
+                } else {
+                    c->tcp_nopush = 1;
+                    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                                   "tcp_nopush");
                 }
             }
 
@@ -185,30 +199,21 @@
             if (rc == -1) {
                 err = ngx_errno;
 
-                if (err == NGX_EINTR) {
-                    eintr = 1;
-
-                } else if (err == NGX_EAGAIN) {
-                    eagain = 1;
-
-                } else if (err == NGX_EPIPE || err == NGX_ENOTCONN) {
-                    level = NGX_LOG_INFO;
-                }
-
                 if (err == NGX_EAGAIN || err == NGX_EINTR) {
+                    if (err == NGX_EINTR) {
+                        eintr = 1;
+
+                    } else {
+                        eagain = 1;
+                    }
+
                     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err,
                                    "sendfile() sent only " OFF_T_FMT " bytes",
                                    sent);
 
                 } 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
+                    ngx_connection_error(c, err, "sendfile() failed");
                     return NGX_CHAIN_ERROR;
                 }
             }
@@ -223,20 +228,17 @@
             if (rc == -1) {
                 err = ngx_errno;
 
-                if (err == NGX_EINTR) {
-                    eintr = 1;
-
-                } else if (err == NGX_EPIPE) {
-                    level = NGX_LOG_INFO;
-                }
-
                 if (err == NGX_EAGAIN || err == NGX_EINTR) {
+                    if (err == NGX_EINTR) {
+                        eintr = 1;
+                    }
+
                     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
                                    "writev() not ready");
 
                 } else {
                     wev->error = 1;
-                    ngx_log_error(level, c->log, err, "writev() failed");
+                    ngx_connection_error(c, err, "writev() failed");
                     return NGX_CHAIN_ERROR;
                 }
             }
@@ -292,8 +294,9 @@
 
             /*
              * sendfile() can return EAGAIN even if it has sent
-             * a whole file part and successive sendfile() would
-             * return EAGAIN right away and would not send anything
+             * a whole file part but the successive sendfile() call would
+             * return EAGAIN right away and would not send anything.
+             * We use it as a hint.
              */
 
             wev->ready = 0;
diff --git a/src/os/unix/ngx_linux_config.h b/src/os/unix/ngx_linux_config.h
index f6b8456..fca68f6 100644
--- a/src/os/unix/ngx_linux_config.h
+++ b/src/os/unix/ngx_linux_config.h
@@ -34,8 +34,17 @@
 #include <netdb.h>
 #include <dirent.h>
 
+
+/* Linux has a broken strerror_r() */
+#define HAVE_STRERROR_R  0
+
 #include <ngx_auto_config.h>
 
+
+#if (HAVE_PRCTL)
+#include <sys/prctl.h>
+#endif
+
 #if (HAVE_SENDFILE64)
 #include <sys/sendfile.h>
 #else
@@ -67,7 +76,7 @@
 
 
 #ifndef HAVE_INHERITED_NONBLOCK
-#define HAVE_INHERITED_NONBLOCK  1
+#define HAVE_INHERITED_NONBLOCK  0
 #endif
 
 
diff --git a/src/os/unix/ngx_linux_sendfile_chain.c b/src/os/unix/ngx_linux_sendfile_chain.c
index 73e2aec..39c2e83 100644
--- a/src/os/unix/ngx_linux_sendfile_chain.c
+++ b/src/os/unix/ngx_linux_sendfile_chain.c
@@ -6,8 +6,8 @@
 
 /*
  * On Linux up to 2.4.21 sendfile() (syscall #187) works with 32-bit
- * 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
+ * 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.
  *
  * Linux 2.4.21 has a new sendfile64() syscall #239.
@@ -80,14 +80,24 @@
             && cl
             && cl->hunk->type & NGX_HUNK_FILE)
         {
-            c->tcp_nopush = 1;
-
-            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,
-                              ngx_tcp_nopush_n " failed");
-                return NGX_CHAIN_ERROR;
+                err = ngx_errno;
+
+                /*
+                 * there is a tiny chance to be interrupted, however
+                 * we continue a processing without the TCP_CORK
+                 */
+
+                if (err != NGX_EINTR) { 
+                    wev->error = 1;
+                    ngx_connection_error(c, err, ngx_tcp_nopush_n " failed");
+                    return NGX_CHAIN_ERROR;
+                }
+
+            } else {
+                c->tcp_nopush = 1;
+                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                               "tcp_nopush");
             }
         }
 
@@ -132,51 +142,52 @@
 
             if (rc == -1) {
                 err = ngx_errno;
-                if (err == NGX_EAGAIN) {
-                    ngx_log_error(NGX_LOG_INFO, c->log, err,
-                                  "sendfile() EAGAIN");
 
-                } else if (err == NGX_EINTR) {
-                    eintr = 1;
-                    ngx_log_error(NGX_LOG_INFO, c->log, err,
-                                  "sendfile() EINTR");
+                if (err == NGX_EAGAIN || err == NGX_EINTR) {
+                    if (err == NGX_EINTR) {
+                        eintr = 1;
+                    }
+
+                    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
+                                   "sendfile() is not ready");
 
                 } else {
-                    ngx_log_error(NGX_LOG_CRIT, c->log, err,
-                                  "sendfile() failed");
+                    wev->error = 1;
+                    ngx_connection_error(c, err, "sendfile() failed");
                     return NGX_CHAIN_ERROR;
                 }
             }
 
             sent = rc > 0 ? rc : 0;
 
-#if (NGX_DEBUG_WRITE_CHAIN)
-            ngx_log_debug(c->log, "sendfile: %d, @" OFF_T_FMT " %d:%d" _
-                          rc _ file->file_pos _ sent _ fsize);
-#endif
+            ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                           "sendfile: %d, @" OFF_T_FMT " %d:%d",
+                           rc, file->file_pos, sent, fsize);
+
         } else {
             rc = writev(c->fd, header.elts, header.nelts);
 
             if (rc == -1) {
                 err = ngx_errno;
-                if (err == NGX_EAGAIN) {
-                    ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EAGAIN");
 
-                } else if (err == NGX_EINTR) {
-                    eintr = 1;
-                    ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EINTR");
+                if (err == NGX_EAGAIN || err == NGX_EINTR) {
+                    if (err == NGX_EINTR) {
+                        eintr = 1;
+                    }
+
+                    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
+                                   "writev() not ready");
 
                 } else {
-                    ngx_log_error(NGX_LOG_CRIT, c->log, err, "writev() failed");
-                    return NGX_CHAIN_ERROR;
+                    wev->error = 1;
+                    ngx_connection_error(c, err, "writev() failed");
+                    return NGX_CHAIN_ERROR; 
                 }
             }
 
             sent = rc > 0 ? rc : 0;
 
-#if (NGX_DEBUG_WRITE_CHAIN)
-            ngx_log_debug(c->log, "writev: %d" _ sent);
-#endif
+            ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %d", sent);
         }
 
         c->sent += sent;
diff --git a/src/os/unix/ngx_recv.c b/src/os/unix/ngx_recv.c
index 1ebbe69..60e2d09 100644
--- a/src/os/unix/ngx_recv.c
+++ b/src/os/unix/ngx_recv.c
@@ -4,14 +4,12 @@
 #include <ngx_event.h>
 
 
-static int ngx_unix_recv_error(ngx_event_t *rev, ngx_err_t err);
-
-
 #if (HAVE_KQUEUE)
 
 ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size)
 {
     ssize_t       n;
+    ngx_err_t     err;
     ngx_event_t  *rev;
 
     rev = c->read;
@@ -26,11 +24,12 @@
                 rev->ready = 0;
                 rev->eof = 1;
 
+                ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
+                              "kevent() reported about an closed connection");
+
                 if (rev->kq_errno) {
                     rev->error = 1;
                     ngx_set_socket_errno(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)
@@ -52,7 +51,8 @@
     do {
         n = recv(c->fd, buf, size, 0);
 
-        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,"recv: %d:%d", n, size);
+        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                       "recv: fd:%d %d of %d", c->fd, n, size);
 
         if (n >= 0) {
             if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
@@ -87,11 +87,19 @@
             return n;
         }
 
-        n = ngx_unix_recv_error(rev, ngx_socket_errno);
+        err = ngx_socket_errno;
 
-    } while (n == NGX_EINTR);
+        if (err == NGX_EAGAIN || err == NGX_EINTR) {
+            ngx_log_debug0(NGX_LOG_DEBUG_EVENT, rev->log, err,
+                           "recv() not ready");
+            n = NGX_AGAIN;
 
-    /* NGX_ERROR || NGX_AGAIN */
+        } else {
+            n = ngx_connection_error(c, err, "recv() failed");
+            break;
+        }
+
+    } while (err == NGX_EINTR);
 
     rev->ready = 0;
 
@@ -107,6 +115,7 @@
 ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size)
 {
     ssize_t       n;
+    ngx_err_t     err;
     ngx_event_t  *rev;
 
     rev = c->read;
@@ -114,7 +123,8 @@
     do {
         n = recv(c->fd, buf, size, 0);
 
-        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,"recv: %d:%d", n, size);
+        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
+                       "recv: fd:%d %d of %d", c->fd, n, size);
 
         if (n >= 0) {
             if ((size_t) n < size) {
@@ -128,11 +138,19 @@
             return n;
         }
 
-        n = ngx_unix_recv_error(rev, ngx_socket_errno);
+        err = ngx_socket_errno;
 
-    } while (n == NGX_EINTR);
+        if (err == NGX_EAGAIN || err == NGX_EINTR) {
+            ngx_log_debug0(NGX_LOG_DEBUG_EVENT, rev->log, err,
+                           "recv() not ready");
+            n = NGX_AGAIN;
 
-    /* NGX_ERROR || NGX_AGAIN */
+        } else {
+            n = ngx_connection_error(c, err, "recv() failed");
+            break;
+        }
+
+    } while (err == NGX_EINTR);
 
     rev->ready = 0;
 
@@ -144,37 +162,3 @@
 }
 
 #endif /* NAVE_KQUEUE */
-
-
-static int ngx_unix_recv_error(ngx_event_t *rev, ngx_err_t err)
-{
-    ngx_int_t  level;
-
-    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_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(level, rev->log, err, "recv() failed");
-
-    return NGX_ERROR;
-}
diff --git a/src/os/unix/ngx_recv.h b/src/os/unix/ngx_recv.h
deleted file mode 100644
index 01d662f..0000000
--- a/src/os/unix/ngx_recv.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _NGX_RECV_H_INCLUDED_
-#define _NGX_RECV_H_INCLUDED_
-
-
-#if 0
-#include <errno.h>
-
-#define ngx_recv(fd, buf, size, flags)  recv(fd, buf, size, flags)
-#endif
-
-
-#endif /* _NGX_RECV_H_INCLUDED_ */
diff --git a/src/os/unix/ngx_socket.c b/src/os/unix/ngx_socket.c
index 8b34c1c..69d3f45 100644
--- a/src/os/unix/ngx_socket.c
+++ b/src/os/unix/ngx_socket.c
@@ -4,12 +4,13 @@
 
 
 /*
-   ioctl(FIONBIO) set blocking mode with one syscall only while
-   fcntl(F_SETFL, ~O_NONBLOCK) need to know previous state
-   using fcntl(F_GETFL).
-
-   ioctl() and fcntl() are syscalls on FreeBSD, Solaris 7/8 and Linux
-*/
+ * ioctl(FIONBIO) sets a blocking mode with the single syscall
+ * while fcntl(F_SETFL, ~O_NONBLOCK) needs to learn before
+ * a previous state using fcntl(F_GETFL).
+ *
+ * ioctl() and fcntl() are syscalls on at least FreeBSD 2.x, Linux 2.2
+ * and Solaris 7
+ */
 
 
 #if (HAVE_FIONBIO)