nginx-0.3.24-RELEASE import

    *) Workaround: for bug in FreeBSD kqueue.

    *) Bugfix: now a response generated by the "post_action" directive is
       not transferred to a client.

    *) Bugfix: the memory leaks were occurring if many log files were used.

    *) Bugfix: the first "proxy_redirect" directive was working inside one
       location.

    *) Bugfix: on 64-bit platforms segmentation fault may occurred on start
       if the many names were used in the "server_name" directives; the bug
       had appeared in 0.3.18.
diff --git a/src/os/unix/ngx_readv_chain.c b/src/os/unix/ngx_readv_chain.c
index b55e2f2..5c2bb5a 100644
--- a/src/os/unix/ngx_readv_chain.c
+++ b/src/os/unix/ngx_readv_chain.c
@@ -111,6 +111,21 @@
                     }
                 }
 
+                if (n == 0) {
+
+                    /*
+                     * on FreeBSD recv() may return 0 on closed socket
+                     * even if kqueue reported about available data
+                     */
+
+                    ngx_log_error(NGX_LOG_ALERT, c->log, 0,
+                                  "recv() returned 0 while kevent() reported "
+                                  "%d available bytes", rev->available);
+
+                    rev->eof = 1;
+                    rev->available = 0;
+                }
+
                 return n;
             }
 
diff --git a/src/os/unix/ngx_recv.c b/src/os/unix/ngx_recv.c
index 0d38729..a8a351a 100644
--- a/src/os/unix/ngx_recv.c
+++ b/src/os/unix/ngx_recv.c
@@ -70,6 +70,21 @@
                     }
                 }
 
+                if (n == 0) {
+
+                    /*
+                     * on FreeBSD recv() may return 0 on closed socket
+                     * even if kqueue reported about available data
+                     */
+
+                    ngx_log_error(NGX_LOG_ALERT, c->log, 0,
+                                  "recv() returned 0 while keevnt() reported "
+                                  "%d available bytes", rev->available);
+
+                    rev->eof = 1;
+                    rev->available = 0;
+                }
+
                 return n;
             }
 
diff --git a/src/os/unix/ngx_shared.c b/src/os/unix/ngx_shared.c
deleted file mode 100644
index 80b5f60..0000000
--- a/src/os/unix/ngx_shared.c
+++ /dev/null
@@ -1,95 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-
-
-#if (NGX_HAVE_MAP_ANON)
-
-void *ngx_create_shared_memory(size_t size, ngx_log_t *log)
-{
-    void  *p;
-
-    p = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
-
-    if (p == MAP_FAILED) {
-        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
-                      "mmap(MAP_ANON|MAP_SHARED, %uz) failed", size);
-        return NULL;
-    }
-
-    return p;
-}
-
-#elif (NGX_HAVE_MAP_DEVZERO)
-
-void *ngx_create_shared_memory(size_t size, ngx_log_t *log)
-{
-    void      *p;
-    ngx_fd_t   fd;
-
-    fd = open("/dev/zero", O_RDWR);
-
-    if (fd == -1) {
-        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
-                      "open(\"/dev/zero\") failed");
-        return NULL;
-    }
-
-    p = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
-
-    if (p == MAP_FAILED) {
-        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
-                      "mmap(/dev/zero, MAP_SHARED, %uz) failed", size);
-        p = NULL;
-    }
-
-    if (close(fd) == -1) {
-        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
-                      "close(\"/dev/zero\") failed");
-    }
-
-    return p;
-}
-
-#elif (NGX_HAVE_SYSVSHM)
-
-#include <sys/ipc.h>
-#include <sys/shm.h>
-
-
-void *ngx_create_shared_memory(size_t size, ngx_log_t *log)
-{
-    int    id;
-    void  *p;
-
-    id = shmget(IPC_PRIVATE, size, (SHM_R|SHM_W|IPC_CREAT));
-
-    if (id == -1) {
-        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
-                      "shmget(%uz) failed", size);
-        return NULL;
-    }
-
-    ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "shmget id: %d", id);
-
-    p = shmat(id, NULL, 0);
-
-    if (p == (void *) -1) {
-        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "shmat() failed");
-        p = NULL;
-    }
-
-    if (shmctl(id, IPC_RMID, NULL) == -1) {
-        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "shmctl(IPC_RMID) failed");
-        p = NULL;
-    }
-
-    return p;
-}
-
-#endif
diff --git a/src/os/unix/ngx_shared.h b/src/os/unix/ngx_shared.h
deleted file mode 100644
index 29e4a33..0000000
--- a/src/os/unix/ngx_shared.h
+++ /dev/null
@@ -1,18 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#ifndef _NGX_SHARED_H_INCLUDED_
-#define _NGX_SHARED_H_INCLUDED_
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-
-
-void *ngx_create_shared_memory(size_t size, ngx_log_t *log);
-
-
-#endif /* _NGX_SHARED_H_INCLUDED_ */
diff --git a/src/os/unix/ngx_shmem.c b/src/os/unix/ngx_shmem.c
new file mode 100644
index 0000000..66df1bb
--- /dev/null
+++ b/src/os/unix/ngx_shmem.c
@@ -0,0 +1,123 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+#if (NGX_HAVE_MAP_ANON)
+
+ngx_int_t
+ngx_shm_alloc(ngx_shm_t *shm)
+{
+    shm->addr = mmap(NULL, shm->size,
+                     PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
+
+    if (shm->addr == MAP_FAILED) {
+        ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
+                      "mmap(MAP_ANON|MAP_SHARED, %uz) failed", shm->size);
+        return NGX_ERROR;
+    }
+
+    return NGX_OK;
+}
+
+
+void
+ngx_shm_free(ngx_shm_t *shm)
+{
+    if (munmap(shm->addr, shm->size) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
+                      "munmap(%p, %uz) failed", shm->addr, shm->size);
+    }
+}
+
+#elif (NGX_HAVE_MAP_DEVZERO)
+
+ngx_int_t
+ngx_shm_alloc(ngx_shm_t *shm)
+{
+    ngx_fd_t  fd;
+
+    fd = open("/dev/zero", O_RDWR);
+
+    if (fd == -1) {
+        ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
+                      "open(\"/dev/zero\") failed");
+        return NGX_ERROR;
+    }
+
+    shm->addr = mmap(NULL, shm->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+
+    if (shm->addr == MAP_FAILED) {
+        ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
+                      "mmap(/dev/zero, MAP_SHARED, %uz) failed", shm->size);
+    }
+
+    if (close(fd) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
+                      "close(\"/dev/zero\") failed");
+    }
+
+    return (shm->addr == MAP_FAILED) ? NGX_ERROR : NGX_OK;
+}
+
+
+void
+ngx_shm_free(ngx_shm_t *shm)
+{
+    if (munmap(shm->addr, shm->size) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
+                      "munmap(%p, %uz) failed", shm->addr, shm->size);
+    }
+}
+
+#elif (NGX_HAVE_SYSVSHM)
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+
+ngx_int_t
+ngx_shm_alloc(ngx_shm_t *shm)
+{
+    int  id;
+
+    id = shmget(IPC_PRIVATE, shm->size, (SHM_R|SHM_W|IPC_CREAT));
+
+    if (id == -1) {
+        ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
+                      "shmget(%uz) failed", shm->size);
+        return NGX_ERROR;
+    }
+
+    ngx_log_debug1(NGX_LOG_DEBUG_CORE, shm->log, 0, "shmget id: %d", id);
+
+    shm->addr = shmat(id, NULL, 0);
+
+    if (shm->addr == (void *) -1) {
+        ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, "shmat() failed");
+    }
+
+    if (shmctl(id, IPC_RMID, NULL) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
+                      "shmctl(IPC_RMID) failed");
+    }
+
+    return (shm->addr == (void *) -1) ? NGX_ERROR : NGX_OK;
+}
+
+
+void
+ngx_shm_free(ngx_shm_t *shm)
+{
+    if (shmdt(shm->addr) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
+                      "shmdt(%p) failed", shm->addr);
+    }
+}
+
+#endif
diff --git a/src/os/unix/ngx_shmem.h b/src/os/unix/ngx_shmem.h
new file mode 100644
index 0000000..72c54f1
--- /dev/null
+++ b/src/os/unix/ngx_shmem.h
@@ -0,0 +1,26 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#ifndef _NGX_SHARED_H_INCLUDED_
+#define _NGX_SHARED_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+typedef struct {
+    u_char      *addr;
+    size_t       size;
+    ngx_log_t   *log;
+} ngx_shm_t;
+
+
+ngx_int_t ngx_shm_alloc(ngx_shm_t *shm);
+void ngx_shm_free(ngx_shm_t *shm);
+
+
+#endif /* _NGX_SHARED_H_INCLUDED_ */