summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2006-11-27 11:18:50 +0000
committerJonathan Kolb <jon@b0g.us>2006-11-27 11:18:50 +0000
commit03789a0a1c208ac62bee429497b9f6a46c0aa5ff (patch)
tree32f1bb5197e419a4dc9c8d7fa2e05eaf86c1998f
parente0cae6b0a5df2466cdb9749dc1a37664fff21ff5 (diff)
downloadnginx-0.4.tar.gz
Changes with nginx 0.4.14 27 Nov 2006v0.4.14nginx-0.4
*) Feature: the "proxy_pass_error_message" directive in IMAP/POP3 proxy. *) Bugfix: ngx_http_perl_module did nto work with perl built with the threads support; bug appeared in 0.3.38. *) Bugfix: !!!!!!!!!! segfault perl. *) Bugfix: !!!!!!!!!! recursive perl. *) Bugfix: nginx ignored a host name in an request line. *) Bugfix: !!!!!!!!!! endless loop when too many FastCGI sent too many to stderr *) Bugfix: !!!!!!!! negative upstream response time *) Bugfix: the "Auth-Login-Attempt" parameter was not sent to IMAP/POP3 proxy authentication server when POP3 was used. *) Bugfix: a segmentation fault might occur if connect to IMAP/POP3 proxy authentication server failed.
-rw-r--r--CHANGES29
-rw-r--r--CHANGES.ru28
-rw-r--r--auto/cc/conf4
-rw-r--r--auto/cc/gcc1
-rw-r--r--auto/cc/sunc1
-rw-r--r--auto/feature8
-rw-r--r--auto/lib/md5/conf19
-rw-r--r--auto/lib/openssl/conf1
-rw-r--r--auto/lib/pcre/conf77
-rw-r--r--auto/lib/perl/conf6
-rw-r--r--auto/lib/sha1/conf18
-rw-r--r--auto/lib/zlib/conf1
-rw-r--r--auto/os/features11
-rw-r--r--auto/os/linux5
-rw-r--r--auto/os/solaris2
-rw-r--r--auto/sources2
-rwxr-xr-xauto/unix15
-rw-r--r--conf/mime.types25
-rw-r--r--src/core/nginx.c36
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_core.h1
-rw-r--r--src/core/ngx_cycle.c138
-rw-r--r--src/core/ngx_cycle.h12
-rw-r--r--src/core/ngx_log.c7
-rw-r--r--src/core/ngx_log.h1
-rw-r--r--src/core/ngx_palloc.c40
-rw-r--r--src/core/ngx_palloc.h4
-rw-r--r--src/core/ngx_rbtree.c128
-rw-r--r--src/core/ngx_rbtree.h11
-rw-r--r--src/core/ngx_shmtx.c13
-rw-r--r--src/core/ngx_shmtx.h16
-rw-r--r--src/core/ngx_slab.c685
-rw-r--r--src/core/ngx_slab.h45
-rw-r--r--src/event/ngx_event.c16
-rw-r--r--src/event/ngx_event_pipe.c8
-rw-r--r--src/event/ngx_event_timer.c1
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/modules/perl/nginx.xs2
-rw-r--r--src/http/modules/perl/ngx_http_perl_module.c224
-rw-r--r--src/http/modules/perl/ngx_http_perl_module.h4
-rw-r--r--src/http/ngx_http_parse.c2
-rw-r--r--src/http/ngx_http_request.c11
-rw-r--r--src/http/ngx_http_upstream.c12
-rw-r--r--src/http/ngx_http_variables.c17
-rw-r--r--src/imap/ngx_imap_auth_http_module.c13
-rw-r--r--src/imap/ngx_imap_handler.c87
-rw-r--r--src/imap/ngx_imap_proxy_module.c63
-rw-r--r--src/os/unix/ngx_alloc.c3
-rw-r--r--src/os/unix/ngx_alloc.h3
-rw-r--r--src/os/unix/ngx_posix_init.c6
50 files changed, 1392 insertions, 474 deletions
diff --git a/CHANGES b/CHANGES
index 424fe3113..e29487937 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,10 +1,35 @@
+Changes with nginx 0.4.14 27 Nov 2006
+
+ *) Feature: the "proxy_pass_error_message" directive in IMAP/POP3 proxy.
+
+ *) Bugfix: ngx_http_perl_module did nto work with perl built with the
+ threads support; bug appeared in 0.3.38.
+
+ *) Bugfix: !!!!!!!!!! segfault perl.
+
+ *) Bugfix: !!!!!!!!!! recursive perl.
+
+ *) Bugfix: nginx ignored a host name in an request line.
+
+ *) Bugfix: !!!!!!!!!! endless loop when too many FastCGI sent too many
+ to stderr
+
+ *) Bugfix: !!!!!!!! negative upstream response time
+
+ *) Bugfix: the "Auth-Login-Attempt" parameter was not sent to IMAP/POP3
+ proxy authentication server when POP3 was used.
+
+ *) Bugfix: a segmentation fault might occur if connect to IMAP/POP3
+ proxy authentication server failed.
+
+
Changes with nginx 0.4.13 15 Nov 2006
*) Feature: the "proxy_pass" directive may be used inside the
- "limit_expect" block.
+ "limit_except" block.
- *) Feature: the "limit_expect" directive supports all WebDAV methods.
+ *) Feature: the "limit_except" directive supports all WebDAV methods.
*) Bugfix: if the "add_before_body" directive was used without the
"add_after_body" directive, then an response did not transferred
diff --git a/CHANGES.ru b/CHANGES.ru
index cc1afdb4e..8471e0758 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,10 +1,34 @@
+Изменения в nginx 0.4.14 27.11.2006
+
+ *) Добавление: директива proxy_pass_error_message в IMAP/POP3 прокси.
+
+ *) Исправление: ngx_http_perl_module не работал с перлом, собранным с
+ поддержкой потоков; ошибка появилась в 0.3.38.
+
+ *) Исправление: !!!!!!!!!!
+
+ *) Исправление: !!!!!!!!!!
+
+ *) Исправление: nginx игнорировал имя сервера в строке запроса.
+
+ *) Исправление: !!!!!!!!!!
+
+ *) Исправление: !!!!!!!!
+
+ *) Исправление: при использовании POP3 серверу аутентификации IMAP/POP3
+ прокси не передавлся параметр Auth-Login-Attempt.
+
+ *) Исправление: при ошибке соединения с сервером аутентификации
+ IMAP/POP3 прокси мог произойти segmentation fault.
+
+
Изменения в nginx 0.4.13 15.11.2006
*) Добавление: директиву proxy_pass можно использовать внутри блока
- limit_expect.
+ limit_except.
- *) Добавление: директива limit_expect поддерживает все WebDAV методы.
+ *) Добавление: директива limit_except поддерживает все WebDAV методы.
*) Исправление: при использовании директивы add_before_body без
директивы add_after_body ответ передавался не полностью.
diff --git a/auto/cc/conf b/auto/cc/conf
index 82854d804..482390029 100644
--- a/auto/cc/conf
+++ b/auto/cc/conf
@@ -113,6 +113,7 @@ if [ "$NGX_PLATFORM" != win32 ]; then
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs=
+ ngx_feature_path=
ngx_feature_libs=
ngx_feature_test=
. auto/feature
@@ -129,6 +130,7 @@ if [ "$NGX_PLATFORM" != win32 ]; then
ngx_feature_run=yes
ngx_feature_incs="#include <stdio.h>
#define var(dummy, args...) sprintf(args)"
+ ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="char buf[30]; buf[0] = '0';
var(0, buf, \"%d\", 1);
@@ -144,6 +146,7 @@ if [ "$NGX_PLATFORM" != win32 ]; then
ngx_feature_run=yes
ngx_feature_incs="#include <stdio.h>
#define var(dummy, ...) sprintf(__VA_ARGS__)"
+ ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="char buf[30]; buf[0] = '0';
var(0, buf, \"%d\", 1);
@@ -156,6 +159,7 @@ if [ "$NGX_PLATFORM" != win32 ]; then
# ngx_feature_name=
# ngx_feature_run=no
# ngx_feature_incs="int inline f(void) { return 1 }"
+# ngx_feature_path=
# ngx_feature_libs=
# ngx_feature_test=
# . auto/feature
diff --git a/auto/cc/gcc b/auto/cc/gcc
index ea515600d..e377fced8 100644
--- a/auto/cc/gcc
+++ b/auto/cc/gcc
@@ -23,6 +23,7 @@ ngx_feature="gcc -pipe switch"
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs=
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test=
. auto/feature
diff --git a/auto/cc/sunc b/auto/cc/sunc
index 00c0674a3..9edc0d098 100644
--- a/auto/cc/sunc
+++ b/auto/cc/sunc
@@ -20,6 +20,7 @@ case "$NGX_MACHINE" in
ngx_feature_name=
ngx_feature_run=bug
ngx_feature_incs=
+ ngx_feature_path=
ngx_feature_libs=
ngx_feature_test='__asm ("pause")'
diff --git a/auto/feature b/auto/feature
index 0cf1f1e18..e71b6e521 100644
--- a/auto/feature
+++ b/auto/feature
@@ -18,6 +18,10 @@ if test -n "$ngx_feature_name"; then
| tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`
fi
+if test -n "$ngx_feature_path"; then
+ ngx_feature_inc_path="-I $ngx_feature_path"
+fi
+
cat << END > $NGX_AUTOTEST.c
#include <sys/types.h>
@@ -32,9 +36,11 @@ int main() {
END
-ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS \
+ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS $ngx_feature_inc_path \
-o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_LD_OPT $ngx_feature_libs"
+ngx_feature_inc_path=
+
eval "$ngx_test >> $NGX_AUTOCONF_ERR 2>&1"
diff --git a/auto/lib/md5/conf b/auto/lib/md5/conf
index 799d0756f..0c80fd59c 100644
--- a/auto/lib/md5/conf
+++ b/auto/lib/md5/conf
@@ -53,6 +53,7 @@ else
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs="#include <md5.h>"
+ ngx_feature_path=
ngx_feature_libs="-lmd5"
ngx_feature_test="MD5_CTX md5; MD5Init(&md5)"
. auto/feature
@@ -70,6 +71,7 @@ else
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs="#include <md5.h>"
+ ngx_feature_path=
ngx_feature_libs="-lmd"
ngx_feature_test="MD5_CTX md5; MD5Init(&md5)"
. auto/feature
@@ -85,15 +87,16 @@ else
else
if [ $MD5 = NO ]; then
- # OpenSSL crypto library
+ # OpenSSL crypto library
- ngx_feature="OpenSSL md5 crypto library"
- ngx_feature_name="NGX_OPENSSL_MD5"
- ngx_feature_run=no
- ngx_feature_incs="#include <openssl/md5.h>"
- ngx_feature_libs="-lcrypto"
- ngx_feature_test="MD5_CTX md5; MD5_Init(&md5)"
- . auto/feature
+ ngx_feature="OpenSSL md5 crypto library"
+ ngx_feature_name="NGX_OPENSSL_MD5"
+ ngx_feature_run=no
+ ngx_feature_incs="#include <openssl/md5.h>"
+ ngx_feature_path=
+ ngx_feature_libs="-lcrypto"
+ ngx_feature_test="MD5_CTX md5; MD5_Init(&md5)"
+ . auto/feature
fi
fi
diff --git a/auto/lib/openssl/conf b/auto/lib/openssl/conf
index 32f82ca7c..02e9e610b 100644
--- a/auto/lib/openssl/conf
+++ b/auto/lib/openssl/conf
@@ -47,6 +47,7 @@ else
ngx_feature_name="NGX_OPENSSL"
ngx_feature_run=no
ngx_feature_incs="#include <openssl/ssl.h>"
+ ngx_feature_path=
ngx_feature_libs="-lssl -lcrypto"
ngx_feature_test="SSL_library_init()"
. auto/feature
diff --git a/auto/lib/pcre/conf b/auto/lib/pcre/conf
index 460325c08..045e6c855 100644
--- a/auto/lib/pcre/conf
+++ b/auto/lib/pcre/conf
@@ -64,13 +64,11 @@ else
if [ "$NGX_PLATFORM" != win32 ]; then
PCRE=NO
- # FreeBSD PCRE port requires --with-cc-opt="-I /usr/local/include"
- # --with-ld-opt="-L /usr/local/lib"
-
ngx_feature="PCRE library"
ngx_feature_name="NGX_PCRE"
ngx_feature_run=no
ngx_feature_incs="#include <pcre.h>"
+ ngx_feature_path=
ngx_feature_libs="-lpcre"
ngx_feature_test="pcre *re; re = pcre_compile(NULL, 0, NULL, 0, NULL)"
. auto/feature
@@ -81,6 +79,79 @@ else
CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
PCRE=YES
ngx_found=no
+
+ else
+ # FreeBSD port
+
+ ngx_feature="PCRE library in /usr/local/"
+ ngx_feature_name="NGX_PCRE"
+ ngx_feature_run=no
+ ngx_feature_incs="#include <pcre.h>"
+ ngx_feature_path="/usr/local/include"
+ ngx_feature_libs="-L /usr/local/lib -lpcre"
+ ngx_feature_test="pcre *re;
+ re = pcre_compile(NULL, 0, NULL, 0, NULL)"
+ . auto/feature
fi
+
+ if [ $ngx_found = yes ]; then
+ CORE_DEPS="$CORE_DEPS $REGEX_DEPS"
+ CORE_SRCS="$CORE_SRCS $REGEX_SRCS"
+ CORE_INCS="$CORE_INCS $ngx_feature_path"
+ CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
+ PCRE=YES
+ ngx_found=no
+
+ else
+ # Linux package
+
+ if [ $PCRE = NO ]; then
+
+ ngx_feature="PCRE library in /usr/include/pcre/"
+ ngx_feature_name="NGX_PCRE"
+ ngx_feature_run=no
+ ngx_feature_incs="#include <pcre.h>"
+ ngx_feature_path="/usr/include/pcre"
+ ngx_feature_libs="-lpcre"
+ ngx_feature_test="pcre *re;
+ re = pcre_compile(NULL, 0, NULL, 0, NULL)"
+ . auto/feature
+ fi
+ fi
+
+ if [ $ngx_found = yes ]; then
+ CORE_DEPS="$CORE_DEPS $REGEX_DEPS"
+ CORE_SRCS="$CORE_SRCS $REGEX_SRCS"
+ CORE_INCS="$CORE_INCS $ngx_feature_path"
+ CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
+ PCRE=YES
+ ngx_found=no
+
+ else
+ # NetBSD port
+
+ if [ $PCRE = NO ]; then
+
+ ngx_feature="PCRE library in /usr/pkg/"
+ ngx_feature_name="NGX_PCRE"
+ ngx_feature_run=no
+ ngx_feature_incs="#include <pcre.h>"
+ ngx_feature_path="/usr/pkg/include"
+ ngx_feature_libs="-L /usr/pkg/lib -lpcre"
+ ngx_feature_test="pcre *re;
+ re = pcre_compile(NULL, 0, NULL, 0, NULL)"
+ . auto/feature
+ fi
+ fi
+
+ if [ $ngx_found = yes ]; then
+ CORE_DEPS="$CORE_DEPS $REGEX_DEPS"
+ CORE_SRCS="$CORE_SRCS $REGEX_SRCS"
+ CORE_INCS="$CORE_INCS $ngx_feature_path"
+ CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
+ PCRE=YES
+ ngx_found=no
+ fi
+
fi
fi
diff --git a/auto/lib/perl/conf b/auto/lib/perl/conf
index e01f9b6c3..2ecaf3a49 100644
--- a/auto/lib/perl/conf
+++ b/auto/lib/perl/conf
@@ -36,11 +36,7 @@ if test -n "$NGX_PERL_VER"; then
echo " + perl interpreter multiplicity found"
fi
- if $NGX_PERL -V:useithreads | grep define > /dev/null; then
- have=NGX_HAVE_PERL_CLONE . auto/have
- echo " + perl_clone() found"
-
- else
+ if $NGX_PERL -V:useithreads | grep undef > /dev/null; then
# FreeBSD port wants to link with -pthread non-threaded perl
ngx_perl_ldopts=`echo $ngx_perl_ldopts | sed 's/ -pthread//'`
fi
diff --git a/auto/lib/sha1/conf b/auto/lib/sha1/conf
index a1e20c9b2..52ca97f59 100644
--- a/auto/lib/sha1/conf
+++ b/auto/lib/sha1/conf
@@ -43,6 +43,7 @@ else
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs="#include <sha.h>"
+ ngx_feature_path=
ngx_feature_libs="-lmd"
ngx_feature_test="SHA_CTX sha1; SHA1_Init(&sha1)"
. auto/feature
@@ -57,15 +58,16 @@ else
else
if [ $SHA1 = NO ]; then
- # OpenSSL crypto library
+ # OpenSSL crypto library
- ngx_feature="OpenSSL sha1 crypto library"
- ngx_feature_name=
- ngx_feature_run=no
- ngx_feature_incs="#include <openssl/sha.h>"
- ngx_feature_libs="-lcrypto"
- ngx_feature_test="SHA_CTX sha1; SHA1_Init(&sha1)"
- . auto/feature
+ ngx_feature="OpenSSL sha1 crypto library"
+ ngx_feature_name=
+ ngx_feature_run=no
+ ngx_feature_incs="#include <openssl/sha.h>"
+ ngx_feature_path=
+ ngx_feature_libs="-lcrypto"
+ ngx_feature_test="SHA_CTX sha1; SHA1_Init(&sha1)"
+ . auto/feature
fi
fi
diff --git a/auto/lib/zlib/conf b/auto/lib/zlib/conf
index 3123c669a..f033354a4 100644
--- a/auto/lib/zlib/conf
+++ b/auto/lib/zlib/conf
@@ -47,6 +47,7 @@ else
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs="#include <zlib.h>"
+ ngx_feature_path=
ngx_feature_libs="-lz"
ngx_feature_test="z_stream z; deflate(&z, Z_NO_FLUSH)"
. auto/feature
diff --git a/auto/os/features b/auto/os/features
index 670de98a0..1e54f9d3d 100644
--- a/auto/os/features
+++ b/auto/os/features
@@ -30,6 +30,7 @@ ngx_feature="poll()"
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs="#include <poll.h>"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="int n, dp; struct pollfd pl;
dp = 0;
@@ -48,6 +49,7 @@ ngx_feature="/dev/poll"
ngx_feature_name="NGX_HAVE_DEVPOLL"
ngx_feature_run=no
ngx_feature_incs="#include <sys/devpoll.h>"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="int n, dp; struct dvpoll dvp;
dp = 0;
@@ -69,6 +71,7 @@ if test -z "$NGX_KQUEUE_CHECKED"; then
ngx_feature_name="NGX_HAVE_KQUEUE"
ngx_feature_run=no
ngx_feature_incs="#include <sys/event.h>"
+ ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="int kq; kq = kqueue()"
. auto/feature
@@ -84,6 +87,7 @@ if test -z "$NGX_KQUEUE_CHECKED"; then
ngx_feature_name="NGX_HAVE_LOWAT_EVENT"
ngx_feature_run=no
ngx_feature_incs="#include <sys/event.h>"
+ ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="struct kevent kev;
kev.fflags = NOTE_LOWAT;"
@@ -95,6 +99,7 @@ if test -z "$NGX_KQUEUE_CHECKED"; then
ngx_feature_run=yes
ngx_feature_incs="#include <sys/event.h>
#include <sys/time.h>"
+ ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="int kq;
struct kevent kev;
@@ -126,6 +131,7 @@ if test -z "$NGX_KQUEUE_CHECKED"; then
ngx_feature_run=bug
ngx_feature_incs="#include <sys/event.h>
#include <sys/time.h>"
+ ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="int kq;
struct kevent kev;
@@ -174,6 +180,7 @@ ngx_feature="crypt()"
ngx_feature_name=
ngx_feature_run=no
ngx_feature_incs=
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="crypt(\"test\", \"salt\");"
. auto/feature
@@ -182,6 +189,10 @@ ngx_feature_test="crypt(\"test\", \"salt\");"
if [ $ngx_found = no ]; then
ngx_feature="crypt() in libcrypt"
+ ngx_feature_name=
+ ngx_feature_run=no
+ ngx_feature_incs=
+ ngx_feature_path=
ngx_feature_libs=-lcrypt
. auto/feature
diff --git a/auto/os/linux b/auto/os/linux
index 413648633..abf61f14a 100644
--- a/auto/os/linux
+++ b/auto/os/linux
@@ -40,6 +40,7 @@ ngx_feature="epoll"
ngx_feature_name="NGX_HAVE_EPOLL"
ngx_feature_run=yes
ngx_feature_incs="#include <sys/epoll.h>"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="int efd = 0, fd = 1, n;
struct epoll_event ee;
@@ -65,6 +66,7 @@ ngx_feature_name="NGX_HAVE_SENDFILE"
ngx_feature_run=yes
ngx_feature_incs="#include <sys/sendfile.h>
#include <errno.h>"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="int s = 0, fd = 1;
ssize_t n; off_t off = 0;
@@ -85,6 +87,7 @@ ngx_feature_name="NGX_HAVE_SENDFILE64"
ngx_feature_run=yes
ngx_feature_incs="#include <sys/sendfile.h>
#include <errno.h>"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="int s = 0, fd = 1;
ssize_t n; off_t off = 0;
@@ -101,6 +104,7 @@ ngx_feature="prctl(PR_SET_DUMPABLE)"
ngx_feature_name="NGX_HAVE_PR_SET_DUMPABLE"
ngx_feature_run=yes
ngx_feature_incs="#include <sys/prctl.h>"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) return 1"
. auto/feature
@@ -112,6 +116,7 @@ ngx_feature="sched_setaffinity()"
ngx_feature_name="NGX_HAVE_SCHED_SETAFFINITY"
ngx_feature_run=no
ngx_feature_incs="#include <sched.h>"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="long mask = 0;
sched_setaffinity(0, 32, (cpu_set_t *) &mask)"
diff --git a/auto/os/solaris b/auto/os/solaris
index 757013d1b..5a46ee661 100644
--- a/auto/os/solaris
+++ b/auto/os/solaris
@@ -28,6 +28,7 @@ ngx_feature="sendfilev()"
ngx_feature_name="NGX_HAVE_SENDFILE"
ngx_feature_run=no
ngx_feature_incs="#include <sys/sendfile.h>"
+ngx_feature_path=
ngx_feature_libs="-lsendfile"
ngx_feature_test="int fd = 1; sendfilevec_t vec[1];
size_t sent; ssize_t n;
@@ -45,6 +46,7 @@ ngx_feature="event ports"
ngx_feature_name="NGX_HAVE_EVENTPORT"
ngx_feature_run=no
ngx_feature_incs="#include <port.h>"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="int n = port_create()"
. auto/feature
diff --git a/auto/sources b/auto/sources
index 253d947c5..c7e0c8d82 100644
--- a/auto/sources
+++ b/auto/sources
@@ -23,6 +23,7 @@ CORE_DEPS="src/core/nginx.h \
src/core/ngx_crc32.h \
src/core/ngx_rbtree.h \
src/core/ngx_radix_tree.h \
+ src/core/ngx_slab.h \
src/core/ngx_times.h \
src/core/ngx_shmtx.h \
src/core/ngx_connection.h \
@@ -46,6 +47,7 @@ CORE_SRCS="src/core/nginx.c \
src/core/ngx_crc32.c \
src/core/ngx_rbtree.c \
src/core/ngx_radix_tree.c \
+ src/core/ngx_slab.c \
src/core/ngx_times.c \
src/core/ngx_shmtx.c \
src/core/ngx_connection.c \
diff --git a/auto/unix b/auto/unix
index 1cf0dc3cd..7c02eccbf 100755
--- a/auto/unix
+++ b/auto/unix
@@ -68,6 +68,7 @@ ngx_feature="setproctitle()"
ngx_feature_name="NGX_HAVE_SETPROCTITLE"
ngx_feature_run=no
ngx_feature_incs=
+ngx_feature_path=
ngx_feature_libs=$NGX_SETPROCTITLE_LIB
ngx_feature_test="setproctitle(\"test\");"
. auto/feature
@@ -77,6 +78,7 @@ ngx_feature="pread()"
ngx_feature_name="NGX_HAVE_PREAD"
ngx_feature_run=no
ngx_feature_incs=
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="char buf[1]; ssize_t n; n = pread(0, buf, 1, 0)"
. auto/feature
@@ -86,6 +88,7 @@ ngx_feature="pwrite()"
ngx_feature_name="NGX_HAVE_PWRITE"
ngx_feature_run=no
ngx_feature_incs=
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="char buf[1]; ssize_t n; n = pwrite(1, buf, 1, 0)"
. auto/feature
@@ -95,6 +98,7 @@ ngx_feature="strerror_r()"
ngx_feature_name="NGX_HAVE_STRERROR_R"
ngx_feature_run=yes
ngx_feature_incs="#include <string.h>"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="char buf[1024]; long n; n = strerror_r(1, buf, 1024);
if (n < 0 || n > 1024) return 1;"
@@ -107,6 +111,7 @@ ngx_feature="gnu style strerror_r()"
ngx_feature_name="NGX_HAVE_GNU_STRERROR_R"
ngx_feature_run=yes
ngx_feature_incs="#include <string.h>"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="char buf[1024]; long n; n = strerror_r(1, buf, 1024);
if (n >= 0 && n < 1024) return 1;"
@@ -117,6 +122,7 @@ ngx_feature="localtime_r()"
ngx_feature_name="NGX_HAVE_LOCALTIME_R"
ngx_feature_run=no
ngx_feature_incs="#include <time.h>"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="struct tm t; time_t c=0; localtime_r(&c, &t)"
. auto/feature
@@ -126,6 +132,7 @@ ngx_feature="posix_memalign()"
ngx_feature_name="NGX_HAVE_POSIX_MEMALIGN"
ngx_feature_run=no
ngx_feature_incs="#include <stdlib.h>"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="void *p; int n; n = posix_memalign(&p, 4096, 4096)"
. auto/feature
@@ -135,6 +142,7 @@ ngx_feature="memalign()"
ngx_feature_name="NGX_HAVE_MEMALIGN"
ngx_feature_run=no
ngx_feature_incs="#include <stdlib.h>"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="void *p; p = memalign(4096, 4096)"
. auto/feature
@@ -144,6 +152,7 @@ ngx_feature="sched_yield()"
ngx_feature_name="NGX_HAVE_SCHED_YIELD"
ngx_feature_run=no
ngx_feature_incs="#include <sched.h>"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="sched_yield()"
. auto/feature
@@ -153,6 +162,7 @@ ngx_feature="mmap(MAP_ANON|MAP_SHARED)"
ngx_feature_name="NGX_HAVE_MAP_ANON"
ngx_feature_run=yes
ngx_feature_incs="#include <sys/mman.h>"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="void *p;
p = mmap(NULL, 4096, PROT_READ|PROT_WRITE,
@@ -167,6 +177,7 @@ ngx_feature_run=yes
ngx_feature_incs="#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test='void *p; int fd;
fd = open("/dev/zero", O_RDWR);
@@ -180,6 +191,7 @@ ngx_feature_name="NGX_HAVE_SYSVSHM"
ngx_feature_run=yes
ngx_feature_incs="#include <sys/ipc.h>
#include <sys/shm.h>"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="int id;
id = shmget(IPC_PRIVATE, 4096, (SHM_R|SHM_W|IPC_CREAT));
@@ -192,6 +204,7 @@ ngx_feature="struct msghdr.msg_control"
ngx_feature_name="NGX_HAVE_MSGHDR_MSG_CONTROL"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="struct msghdr msg; msg.msg_control = NULL"
. auto/feature
@@ -202,6 +215,7 @@ ngx_feature_name="NGX_HAVE_FIONBIO"
ngx_feature_run=no
ngx_feature_incs="#include <sys/ioctl.h>
$NGX_INCLUDE_SYS_FILIO_H"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="int i; i = FIONBIO"
. auto/feature
@@ -211,6 +225,7 @@ ngx_feature="struct tm.tm_gmtoff"
ngx_feature_name="NGX_HAVE_GMTOFF"
ngx_feature_run=no
ngx_feature_incs="#include <time.h>"
+ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="struct tm tm; tm.tm_gmtoff = 0"
. auto/feature
diff --git a/conf/mime.types b/conf/mime.types
index 497308b9c..904f255bb 100644
--- a/conf/mime.types
+++ b/conf/mime.types
@@ -7,18 +7,29 @@ types {
image/jpeg jpeg jpg;
application/x-javascript js;
+ text/mathml mml;
text/plain txt;
+ text/vnd.sun.j2me.app-descriptor jad;
+ text/vnd.wap.wml wml;
text/x-component htc;
- text/mathml mml;
image/png png;
+ image/tiff tif tiff;
+ image/vnd.wap.wbmp wbmp;
image/x-icon ico;
image/x-jng jng;
- image/vnd.wap.wbmp wbmp;
+ image/x-ms-bmp bmp;
application/java-archive jar war ear;
application/mac-binhex40 hqx;
+ application/msword doc;
application/pdf pdf;
+ application/postscript ps eps ai;
+ application/rtf rtf;
+ application/vnd.ms-excel xls;
+ application/vnd.ms-powerpoint ppt;
+ application/vnd.wap.wmlc wmlc;
+ application/vnd.wap.xhtml+xml xhtml;
application/x-cocoa cco;
application/x-java-archive-diff jardiff;
application/x-java-jnlp-file jnlp;
@@ -35,21 +46,23 @@ types {
application/x-xpinstall xpi;
application/zip zip;
- application/octet-stream deb;
application/octet-stream bin exe dll;
+ application/octet-stream deb;
application/octet-stream dmg;
application/octet-stream eot;
application/octet-stream iso img;
application/octet-stream msi msp msm;
+ audio/midi mid midi kar;
audio/mpeg mp3;
audio/x-realaudio ra;
+ video/3gpp 3gpp 3gp;
video/mpeg mpeg mpg;
video/quicktime mov;
video/x-flv flv;
- video/x-msvideo avi;
- video/x-ms-wmv wmv;
- video/x-ms-asf asx asf;
video/x-mng mng;
+ video/x-ms-asf asx asf;
+ video/x-ms-wmv wmv;
+ video/x-msvideo avi;
}
diff --git a/src/core/nginx.c b/src/core/nginx.c
index a3f9ce3d8..83b088ba8 100644
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -621,6 +621,7 @@ ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf)
ngx_core_conf_t *ccf = conf;
#if !(NGX_WIN32)
+ ngx_str_t lock_file;
struct passwd *pwd;
struct group *grp;
#endif
@@ -697,6 +698,7 @@ ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf)
ngx_memcpy(ngx_cpymem(ccf->oldpid.data, ccf->pid.data, ccf->pid.len),
NGX_OLDPID_EXT, sizeof(NGX_OLDPID_EXT));
+
if (ccf->lock_file.len == 0) {
ccf->lock_file.len = sizeof(NGX_LOCK_PATH) - 1;
ccf->lock_file.data = (u_char *) NGX_LOCK_PATH;
@@ -706,6 +708,40 @@ ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf)
return NGX_CONF_ERROR;
}
+ lock_file = cycle->old_cycle->lock_file;
+
+ if (lock_file.len) {
+ lock_file.len--;
+
+ if (ccf->lock_file.len != lock_file.len
+ || ngx_strncmp(ccf->lock_file.data, lock_file.data, lock_file.len)
+ != 0)
+ {
+ ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
+ "\"lock_file\" could not be changed, ignored");
+ }
+
+ cycle->lock_file.len = lock_file.len + 1;
+ lock_file.len += sizeof(".accept");
+
+ cycle->lock_file.data = ngx_pstrdup(cycle->pool, &lock_file);
+ if (cycle->lock_file.data == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ } else {
+ cycle->lock_file.len = ccf->lock_file.len + 1;
+ cycle->lock_file.data = ngx_palloc(cycle->pool,
+ ccf->lock_file.len + sizeof(".accept"));
+ if (cycle->lock_file.data == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ ngx_memcpy(ngx_cpymem(cycle->lock_file.data, ccf->lock_file.data,
+ ccf->lock_file.len),
+ ".accept", sizeof(".accept"));
+ }
+
#endif
return NGX_CONF_OK;
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 86d1f7633..c7127ed90 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VERSION "0.4.13"
+#define NGINX_VERSION "0.4.14"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h
index 7c1fbbdff..ec8bbf3ae 100644
--- a/src/core/ngx_core.h
+++ b/src/core/ngx_core.h
@@ -64,6 +64,7 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c);
#include <ngx_radix_tree.h>
#include <ngx_times.h>
#include <ngx_shmtx.h>
+#include <ngx_slab.h>
#if (NGX_OPENSSL)
#include <ngx_event_openssl.h>
#endif
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index baf25ea95..736600f0d 100644
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -43,12 +43,15 @@ ngx_cycle_t *
ngx_init_cycle(ngx_cycle_t *old_cycle)
{
void *rv;
+ u_char *lock_file;
ngx_uint_t i, n;
ngx_log_t *log;
ngx_conf_t conf;
ngx_pool_t *pool;
ngx_cycle_t *cycle, **old;
- ngx_list_part_t *part;
+ ngx_shm_zone_t *shm, *oshm;
+ ngx_slab_pool_t *shpool;
+ ngx_list_part_t *part, *opart;
ngx_open_file_t *file;
ngx_listening_t *ls, *nls;
ngx_core_conf_t *ccf;
@@ -120,6 +123,25 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
}
+ if (old_cycle->shared_memory.part.nelts) {
+ n = old_cycle->shared_memory.part.nelts;
+ for (part = old_cycle->shared_memory.part.next; part; part = part->next)
+ {
+ n += part->nelts;
+ }
+
+ } else {
+ n = 1;
+ }
+
+ if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t))
+ == NGX_ERROR)
+ {
+ ngx_destroy_pool(pool);
+ return NULL;
+ }
+
+
cycle->new_log = ngx_log_create_errlog(cycle, NULL);
if (cycle->new_log == NULL) {
ngx_destroy_pool(pool);
@@ -183,21 +205,6 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
}
-#if 0
- cycle->shm.size = /* STUB */ ngx_pagesize;
- cycle->shm.log = log;
-
- if (ngx_shm_alloc(&cycle->shm) != NGX_OK) {
- ngx_destroy_pool(conf.temp_pool);
- ngx_destroy_pool(pool);
- return NULL;
- }
-
- cycle->shm_last = cycle->shm.addr;
- cycle->shm_end = cycle->shm.addr + cycle->shm.size;
-#endif
-
-
conf.ctx = cycle->conf_ctx;
conf.cycle = cycle;
conf.pool = pool;
@@ -274,7 +281,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
#endif
- if (ngx_test_lockfile(ccf->lock_file.data, log) != NGX_OK) {
+ if (ngx_test_lockfile(cycle->lock_file.data, log) != NGX_OK) {
goto failed;
}
@@ -343,6 +350,94 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
}
+ /* create shared memory */
+
+ part = &cycle->shared_memory.part;
+ shm = part->elts;
+
+ for (i = 0; /* void */ ; i++) {
+
+ if (i >= part->nelts) {
+ if (part->next == NULL) {
+ break;
+ }
+ part = part->next;
+ shm = part->elts;
+ i = 0;
+ }
+
+ shm[i].shm.log = cycle->log;
+
+ opart = &old_cycle->shared_memory.part;
+ oshm = opart->elts;
+
+ for (n = 0; /* void */ ; n++) {
+
+ if (n >= opart->nelts) {
+ if (opart->next == NULL) {
+ break;
+ }
+ opart = opart->next;
+ oshm = opart->elts;
+ n = 0;
+ }
+
+ if (ngx_strcmp(shm[i].name.data, oshm[n].name.data) != 0) {
+ continue;
+ }
+
+ if (shm[i].shm.size == oshm[n].shm.size) {
+ shm[i].shm.addr = oshm[n].shm.addr;
+ goto found;
+ }
+
+ ngx_shm_free(&oshm[n].shm);
+
+ break;
+ }
+
+ if (ngx_shm_alloc(&shm[i].shm) != NGX_OK) {
+ goto failed;
+ }
+
+ shpool = (ngx_slab_pool_t *) shm[i].shm.addr;
+
+ shpool->end = shm[i].shm.addr + shm[i].shm.size;
+ shpool->min_shift = 3;
+
+#if (NGX_HAVE_ATOMIC_OPS)
+
+ lock_file = NULL;
+
+#else
+
+ lock_file = ngx_palloc(cycle->pool,
+ cycle->lock_file.len + shm[i].name.len);
+
+ if (lock_file == NULL) {
+ goto failed;
+ }
+
+ (void) ngx_cpystrn(ngx_cpymem(lock_file, cycle->lock_file.data,
+ cycle->lock_file.len),
+ shm[i].name.data, shm[i].name.len + 1);
+
+#endif
+
+ if (ngx_shmtx_create(&shpool->mutex, (void *) &shpool->lock, lock_file)
+ != NGX_OK)
+ {
+ goto failed;
+ }
+
+ ngx_slab_init(shpool);
+
+ found:
+
+ continue;
+ }
+
+
/* handle the listening sockets */
if (old_cycle->listening.nelts) {
@@ -521,12 +616,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
if (ngx_process == NGX_PROCESS_MASTER || ngx_is_init_cycle(old_cycle)) {
- if (old_cycle->shm.addr) {
- ngx_shm_free(&old_cycle->shm);
- }
-
ngx_destroy_pool(old_cycle->pool);
-
cycle->old_cycle = NULL;
return cycle;
@@ -630,10 +720,6 @@ failed:
static void
ngx_destroy_cycle_pools(ngx_conf_t *conf)
{
- if (conf->cycle->shm.addr) {
- ngx_shm_free(&conf->cycle->shm);
- }
-
ngx_destroy_pool(conf->temp_pool);
ngx_destroy_pool(conf->pool);
}
diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h
index ad92ff2df..e1a35eb75 100644
--- a/src/core/ngx_cycle.h
+++ b/src/core/ngx_cycle.h
@@ -21,6 +21,12 @@
#define NGX_DEBUG_POINTS_ABORT 2
+typedef struct {
+ ngx_shm_t shm;
+ ngx_str_t name;
+} ngx_shm_zone_t;
+
+
struct ngx_cycle_s {
void ****conf_ctx;
ngx_pool_t *pool;
@@ -32,13 +38,10 @@ struct ngx_cycle_s {
ngx_connection_t *free_connections;
ngx_uint_t free_connection_n;
- ngx_shm_t shm;
- u_char *shm_last;
- u_char *shm_end;
-
ngx_array_t listening;
ngx_array_t pathes;
ngx_list_t open_files;
+ ngx_list_t shared_memory;
ngx_uint_t connection_n;
ngx_uint_t files_n;
@@ -51,6 +54,7 @@ struct ngx_cycle_s {
ngx_str_t conf_file;
ngx_str_t root;
+ ngx_str_t lock_file;
};
diff --git a/src/core/ngx_log.c b/src/core/ngx_log.c
index 21d59780f..ea4e7f2f4 100644
--- a/src/core/ngx_log.c
+++ b/src/core/ngx_log.c
@@ -190,6 +190,13 @@ ngx_log_debug_core(ngx_log_t *log, ngx_err_t err, const char *fmt, ...)
#endif
+void
+ngx_log_abort(ngx_err_t err, const char *text)
+{
+ ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err, text);
+}
+
+
ngx_log_t *
ngx_log_init(void)
{
diff --git a/src/core/ngx_log.h b/src/core/ngx_log.h
index d49f9d1fe..2f70950cf 100644
--- a/src/core/ngx_log.h
+++ b/src/core/ngx_log.h
@@ -201,6 +201,7 @@ void ngx_cdecl ngx_log_debug_core(ngx_log_t *log, ngx_err_t err,
ngx_log_t *ngx_log_init(void);
ngx_log_t *ngx_log_create_errlog(ngx_cycle_t *cycle, ngx_array_t *args);
char *ngx_set_error_log_levels(ngx_conf_t *cf, ngx_log_t *log);
+void ngx_log_abort(ngx_err_t err, const char *text);
extern ngx_module_t ngx_errlog_module;
diff --git a/src/core/ngx_palloc.c b/src/core/ngx_palloc.c
index 1797e96d0..a0f0085d0 100644
--- a/src/core/ngx_palloc.c
+++ b/src/core/ngx_palloc.c
@@ -193,46 +193,6 @@ ngx_pcalloc(ngx_pool_t *pool, size_t size)
}
-void *
-ngx_shalloc(size_t size)
-{
- u_char *p;
-
- if (size < sizeof(int) || (size & 1)) {
- p = ngx_cycle->shm_last;
-
- } else {
- p = ngx_align_ptr(ngx_cycle->shm_last, NGX_ALIGNMENT);
- }
-
- if ((size_t) (ngx_cycle->shm_end - p) >= size) {
- ngx_cycle->shm_last = p + size;
- return p;
- }
-
- ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, 0,
- "allocation of %uz bytes in shared memory failed, "
- "only %uz are available",
- size, ngx_cycle->shm_end - ngx_cycle->shm_last);
-
- return NULL;
-}
-
-
-void *
-ngx_shcalloc(size_t size)
-{
- void *p;
-
- p = ngx_shalloc(size);
- if (p) {
- ngx_memzero(p, size);
- }
-
- return p;
-}
-
-
ngx_pool_cleanup_t *
ngx_pool_cleanup_add(ngx_pool_t *p, size_t size)
{
diff --git a/src/core/ngx_palloc.h b/src/core/ngx_palloc.h
index 85e77f50d..239728102 100644
--- a/src/core/ngx_palloc.h
+++ b/src/core/ngx_palloc.h
@@ -71,10 +71,6 @@ void *ngx_palloc(ngx_pool_t *pool, size_t size);
void *ngx_pcalloc(ngx_pool_t *pool, size_t size);
ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p);
-void *ngx_shalloc(size_t size);
-void *ngx_shcalloc(size_t size);
-void ngx_shfree(void *p);
-
ngx_pool_cleanup_t *ngx_pool_cleanup_add(ngx_pool_t *p, size_t size);
void ngx_pool_cleanup_file(void *data);
diff --git a/src/core/ngx_rbtree.c b/src/core/ngx_rbtree.c
index 3c42be402..a9d630520 100644
--- a/src/core/ngx_rbtree.c
+++ b/src/core/ngx_rbtree.c
@@ -47,53 +47,10 @@ ngx_rbtree_insert(ngx_thread_volatile ngx_rbtree_t *tree,
return;
}
- /*
- * The rbtree is currently used by event timers only. Timer values
- * 1) are spread in small range, usually several minutes,
- * 2) and overflow each 49 days, if milliseconds are stored in 32 bits.
- * The below comparison takes into account that overflow.
- *
- * If there will be a necessity to use the rbtree for values with
- * other comparison rules, then a whole "for ( ;; )" loop should
- * be made as tree->insert() function.
- */
-
- temp = *root;
-
- for ( ;; ) {
-
- /* node->key < temp->key */
-
- if ((ngx_rbtree_key_int_t) node->key - (ngx_rbtree_key_int_t) temp->key
- < 0)
- {
- if (temp->left == sentinel) {
- temp->left = node;
- break;
- }
-
- temp = temp->left;
- continue;
- }
-
- if (temp->right == sentinel) {
- temp->right = node;
- break;
- }
-
- temp = temp->right;
- continue;
- }
-
- node->parent = temp;
- node->left = sentinel;
- node->right = sentinel;
-
+ tree->insert(*root, node, sentinel);
/* re-balance tree */
- ngx_rbt_red(node);
-
while (node != *root && ngx_rbt_is_red(node->parent)) {
if (node->parent == node->parent->parent->left) {
@@ -136,7 +93,6 @@ ngx_rbtree_insert(ngx_thread_volatile ngx_rbtree_t *tree,
ngx_rbtree_left_rotate(root, sentinel, node->parent->parent);
}
}
-
}
ngx_rbt_black(*root);
@@ -144,10 +100,86 @@ ngx_rbtree_insert(ngx_thread_volatile ngx_rbtree_t *tree,
void
+ngx_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node,
+ ngx_rbtree_node_t *sentinel)
+{
+ for ( ;; ) {
+
+ if (node->key < temp->key) {
+
+ if (temp->left == sentinel) {
+ temp->left = node;
+ break;
+ }
+
+ temp = temp->left;
+
+ } else {
+
+ if (temp->right == sentinel) {
+ temp->right = node;
+ break;
+ }
+
+ temp = temp->right;
+ }
+ }
+
+ node->parent = temp;
+ node->left = sentinel;
+ node->right = sentinel;
+ ngx_rbt_red(node);
+}
+
+
+void
+ngx_rbtree_insert_timer_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node,
+ ngx_rbtree_node_t *sentinel)
+{
+ for ( ;; ) {
+
+ /*
+ * Timer values
+ * 1) are spread in small range, usually several minutes,
+ * 2) and overflow each 49 days, if milliseconds are stored in 32 bits.
+ * The comparison takes into account that overflow.
+ */
+
+ if ((ngx_rbtree_key_int_t) node->key - (ngx_rbtree_key_int_t) temp->key
+ < 0)
+ {
+ /* node->key < temp->key */
+
+ if (temp->left == sentinel) {
+ temp->left = node;
+ break;
+ }
+
+ temp = temp->left;
+
+ } else {
+
+ if (temp->right == sentinel) {
+ temp->right = node;
+ break;
+ }
+
+ temp = temp->right;
+ }
+ }
+
+ node->parent = temp;
+ node->left = sentinel;
+ node->right = sentinel;
+ ngx_rbt_red(node);
+}
+
+
+void
ngx_rbtree_delete(ngx_thread_volatile ngx_rbtree_t *tree,
ngx_rbtree_node_t *node)
{
- ngx_int_t is_red;
+ ngx_uint_t red;
ngx_rbtree_node_t **root, *sentinel, *subst, *temp, *w;
/* a binary tree delete */
@@ -186,7 +218,7 @@ ngx_rbtree_delete(ngx_thread_volatile ngx_rbtree_t *tree,
return;
}
- is_red = ngx_rbt_is_red(subst);
+ red = ngx_rbt_is_red(subst);
if (subst == subst->parent->left) {
subst->parent->left = temp;
@@ -239,7 +271,7 @@ ngx_rbtree_delete(ngx_thread_volatile ngx_rbtree_t *tree,
node->key = 0;
}
- if (is_red) {
+ if (red) {
return;
}
diff --git a/src/core/ngx_rbtree.h b/src/core/ngx_rbtree.h
index a57ec778d..008db2a25 100644
--- a/src/core/ngx_rbtree.h
+++ b/src/core/ngx_rbtree.h
@@ -23,19 +23,20 @@ struct ngx_rbtree_node_s {
ngx_rbtree_node_t *left;
ngx_rbtree_node_t *right;
ngx_rbtree_node_t *parent;
- char color;
+ u_char color;
+ u_char data;
};
typedef struct ngx_rbtree_s ngx_rbtree_t;
-typedef ngx_rbtree_node_t *(*ngx_rbtree_insert_pt) (ngx_rbtree_node_t *root,
+typedef void (*ngx_rbtree_insert_pt) (ngx_rbtree_node_t *root,
ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
struct ngx_rbtree_s {
ngx_rbtree_node_t *root;
ngx_rbtree_node_t *sentinel;
- /* ngx_rbtree_insert_pt insert; */
+ ngx_rbtree_insert_pt insert;
};
@@ -43,6 +44,10 @@ void ngx_rbtree_insert(ngx_thread_volatile ngx_rbtree_t *tree,
ngx_rbtree_node_t *node);
void ngx_rbtree_delete(ngx_thread_volatile ngx_rbtree_t *tree,
ngx_rbtree_node_t *node);
+void ngx_rbtree_insert_value(ngx_rbtree_node_t *root, ngx_rbtree_node_t *node,
+ ngx_rbtree_node_t *sentinel);
+void ngx_rbtree_insert_timer_value(ngx_rbtree_node_t *root,
+ ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
static ngx_inline ngx_rbtree_node_t *
diff --git a/src/core/ngx_shmtx.c b/src/core/ngx_shmtx.c
index ac8a30010..0d3b09616 100644
--- a/src/core/ngx_shmtx.c
+++ b/src/core/ngx_shmtx.c
@@ -12,7 +12,7 @@
ngx_int_t
-ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name, ngx_log_t *log)
+ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name)
{
mtx->lock = addr;
@@ -23,14 +23,12 @@ ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name, ngx_log_t *log)
ngx_int_t
-ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name, ngx_log_t *log)
+ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name)
{
if (mtx->name) {
if (ngx_strcmp(name, mtx->name) == 0) {
mtx->name = name;
- mtx->log = log;
-
return NGX_OK;
}
@@ -40,18 +38,17 @@ ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name, ngx_log_t *log)
mtx->fd = ngx_open_file(name, NGX_FILE_RDWR, NGX_FILE_CREATE_OR_OPEN);
if (mtx->fd == NGX_INVALID_FILE) {
- ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
+ ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, ngx_errno,
ngx_open_file_n " \"%s\" failed", name);
return NGX_ERROR;
}
if (ngx_delete_file(name) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+ ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
ngx_delete_file_n " \"%s\" failed", name);
}
mtx->name = name;
- mtx->log = log;
return NGX_OK;
}
@@ -61,7 +58,7 @@ void
ngx_shmtx_destory(ngx_shmtx_t *mtx)
{
if (ngx_close_file(mtx->fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, mtx->log, ngx_errno,
+ ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
ngx_close_file_n " \"%s\" failed", mtx->name);
}
}
diff --git a/src/core/ngx_shmtx.h b/src/core/ngx_shmtx.h
index fdd62e192..1361125de 100644
--- a/src/core/ngx_shmtx.h
+++ b/src/core/ngx_shmtx.h
@@ -18,13 +18,11 @@ typedef struct {
#else
ngx_fd_t fd;
u_char *name;
- ngx_log_t *log;
#endif
} ngx_shmtx_t;
-ngx_int_t ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name,
- ngx_log_t *log);
+ngx_int_t ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name);
#if (NGX_HAVE_ATOMIC_OPS)
@@ -63,9 +61,7 @@ ngx_shmtx_trylock(ngx_shmtx_t *mtx)
return 0;
}
- ngx_log_error(NGX_LOG_ALERT, mtx->log, err, ngx_trylock_fd_n " failed");
-
- ngx_abort();
+ ngx_log_abort(err, ngx_trylock_fd_n " failed");
}
@@ -80,9 +76,7 @@ ngx_shmtx_lock(ngx_shmtx_t *mtx)
return;
}
- ngx_log_error(NGX_LOG_ALERT, mtx->log, err, ngx_lock_fd_n " failed");
-
- ngx_abort();
+ ngx_log_abort(err, ngx_lock_fd_n " failed");
}
@@ -97,9 +91,7 @@ ngx_shmtx_unlock(ngx_shmtx_t *mtx)
return;
}
- ngx_log_error(NGX_LOG_ALERT, mtx->log, err, ngx_unlock_fd_n " failed");
-
- ngx_abort();
+ ngx_log_abort(err, ngx_unlock_fd_n " failed");
}
diff --git a/src/core/ngx_slab.c b/src/core/ngx_slab.c
new file mode 100644
index 000000000..e182b7a1a
--- /dev/null
+++ b/src/core/ngx_slab.c
@@ -0,0 +1,685 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+/*
+
+ 12
+ 2048 2 11
+ 1024 4 10
+ 512 8 9
+ 256 16 8
+
+ 128 32 4 32 7
+
+ 64 64 8 63 6 1
+ 32 128 16 127 5 1
+ 16 256 32 254 4 2
+ 8 512 64 504 3 8
+
+ */
+
+
+#define NGX_SLAB_PAGE_MASK 3
+#define NGX_SLAB_PAGE 0
+#define NGX_SLAB_BIG 1
+#define NGX_SLAB_EXACT 2
+#define NGX_SLAB_SMALL 3
+
+#if (NGX_PTR_SIZE == 4)
+
+#define NGX_SLAB_PAGE_FREE 0
+#define NGX_SLAB_PAGE_BUSY 0xffffffff
+#define NGX_SLAB_PAGE_START 0x80000000
+
+#define NGX_SLAB_SHIFT_MASK 0x0000000f
+#define NGX_SLAB_MAP_MASK 0xffff0000
+#define NGX_SLAB_MAP_SHIFT 16
+
+#define NGX_SLAB_BUSY 0xffffffff
+
+#else /* (NGX_PTR_SIZE == 8) */
+
+#define NGX_SLAB_PAGE_FREE 0
+#define NGX_SLAB_PAGE_BUSY 0xffffffffffffffff
+#define NGX_SLAB_PAGE_START 0x8000000000000000
+
+#define NGX_SLAB_SHIFT_MASK 0x000000000000000f
+#define NGX_SLAB_MAP_MASK 0xffffffff00000000
+#define NGX_SLAB_MAP_SHIFT 32
+
+#define NGX_SLAB_BUSY 0xffffffffffffffff
+
+#endif
+
+
+#if (NGX_DEBUG_MALLOC)
+#define ngx_slab_junk(p, size) ngx_memset(p, 0xD0, size)
+#else
+#define ngx_slab_junk(p, size)
+#endif
+
+static ngx_slab_page_t *ngx_slab_alloc_pages(ngx_slab_pool_t *pool,
+ ngx_uint_t pages);
+static void ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page,
+ ngx_uint_t pages);
+
+
+static ngx_uint_t ngx_slab_max_size;
+static ngx_uint_t ngx_slab_exact_size;
+static ngx_uint_t ngx_slab_exact_shift;
+
+
+void
+ngx_slab_init(ngx_slab_pool_t *pool)
+{
+ u_char *p;
+ size_t size;
+ ngx_int_t m;
+ ngx_uint_t i, n, pages;
+ ngx_slab_page_t *slots;
+
+ /* STUB */
+ if (ngx_slab_max_size == 0) {
+ ngx_slab_max_size = ngx_pagesize / 2;
+ ngx_slab_exact_size = ngx_pagesize / (8 * sizeof(uintptr_t));
+ for (n = ngx_slab_exact_size; n >>= 1; ngx_slab_exact_shift++) {
+ /* void */
+ }
+ }
+ /**/
+
+ pool->min_size = 1 << pool->min_shift;
+
+ p = (u_char *) pool + sizeof(ngx_slab_pool_t);
+ size = pool->end - p;
+
+ ngx_slab_junk(p, size);
+
+ slots = (ngx_slab_page_t *) p;
+ n = ngx_pagesize_shift - pool->min_shift;
+
+ for (i = 0; i < n; i++) {
+ slots[i].slab = 0;
+ slots[i].next = &slots[i];
+ slots[i].prev = 0;
+ }
+
+ p += n * sizeof(ngx_slab_page_t);
+
+ /* STUB: possible overflow on 64-bit platform */
+ pages = (ngx_uint_t) ((uint64_t) size * ngx_pagesize
+ / (ngx_pagesize + sizeof(ngx_slab_page_t))
+ / ngx_pagesize);
+
+ ngx_memzero(p, pages * sizeof(ngx_slab_page_t));
+
+ pool->pages = (ngx_slab_page_t *) p;
+
+ pool->free.prev = 0;
+ pool->free.next = (ngx_slab_page_t *) p;
+
+ pool->pages->slab = pages;
+ pool->pages->next = &pool->free;
+ pool->pages->prev = (uintptr_t) &pool->free;
+
+ pool->start = (u_char *)
+ ngx_align((uintptr_t) p + pages * sizeof(ngx_slab_page_t),
+ ngx_pagesize);
+
+ m = pages - (pool->end - pool->start) / ngx_pagesize;
+ if (m > 0) {
+ pages -= m;
+ pool->pages->slab = pages;
+ }
+
+#if 0
+ ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "slab: %p, %p, %ui, %d",
+ pool, pool->start, pages,
+ (pool->end - pool->start) / ngx_pagesize - pages);
+#endif
+}
+
+
+void *
+ngx_slab_alloc(ngx_slab_pool_t *pool, size_t size)
+{
+ size_t s;
+ uintptr_t p, mask, *bitmap;
+ ngx_uint_t i, n, m, slot, shift, map;
+ ngx_slab_page_t *page, *prev, *slots;
+
+ ngx_shmtx_lock(&pool->mutex);
+
+ if (size >= ngx_slab_max_size) {
+ page = ngx_slab_alloc_pages(pool, (size + ngx_pagesize - 1)
+ >> ngx_pagesize_shift);
+ if (page) {
+ p = (page - pool->pages) << ngx_pagesize_shift;
+ p += (uintptr_t) pool->start;
+
+ } else {
+ p = 0;
+ }
+
+ goto done;
+ }
+
+ if (size > pool->min_size) {
+ shift = 1;
+ for (s = size - 1; s >>= 1; shift++) { /* void */ }
+ slot = shift - pool->min_shift;
+
+ } else {
+ size = pool->min_size;
+ shift = pool->min_shift;
+ slot = 0;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0,
+ "slab alloc: %uz slot: %ui", size, slot);
+
+ slots = (ngx_slab_page_t *) ((u_char *) pool + sizeof(ngx_slab_pool_t));
+ page = slots[slot].next;
+
+#if 0
+ ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0,
+ "slab alloc: page %p next: %p", page, page->next);
+#endif
+
+ if (page->next != page) {
+
+ if (size < ngx_slab_exact_size) {
+
+ do {
+ p = (page - pool->pages) << ngx_pagesize_shift;
+ bitmap = (uintptr_t *) (pool->start + p);
+
+ map = (1 << (ngx_pagesize_shift - shift))
+ / (sizeof(uintptr_t) * 8);
+
+ for (n = 0; n < map; n++) {
+
+ if (bitmap[n] != NGX_SLAB_BUSY) {
+
+ for (m = 1, i = 0; m; m <<= 1, i++) {
+ if ((bitmap[n] & m)) {
+ continue;
+ }
+
+ bitmap[n] |= m;
+ i <<= shift;
+
+ if (bitmap[n] == NGX_SLAB_BUSY) {
+ for (n = n + 1; n < map; n++) {
+ if (bitmap[n] != NGX_SLAB_BUSY) {
+ p = (uintptr_t) bitmap + i;
+
+ goto done;
+ }
+ }
+
+ prev = (ngx_slab_page_t *)
+ (page->prev & ~NGX_SLAB_PAGE_MASK);
+ prev->next = page->next;
+ page->next->prev = page->prev;
+
+ page->next = NULL;
+ page->prev = NGX_SLAB_SMALL;
+ }
+
+ p = (uintptr_t) bitmap + i;
+
+ goto done;
+ }
+ }
+ }
+
+ page = page->next;
+
+ } while (page);
+
+ } else if (size == ngx_slab_exact_size) {
+
+ do {
+ if (page->slab != NGX_SLAB_BUSY) {
+
+ for (m = 1, i = 0; m; m <<= 1, i++) {
+ if ((page->slab & m)) {
+ continue;
+ }
+
+ page->slab |= m;
+
+ if (page->slab == NGX_SLAB_BUSY) {
+ prev = (ngx_slab_page_t *)
+ (page->prev & ~NGX_SLAB_PAGE_MASK);
+ prev->next = page->next;
+ page->next->prev = page->prev;
+
+ page->next = NULL;
+ page->prev = NGX_SLAB_EXACT;
+ }
+
+ p = (page - pool->pages) << ngx_pagesize_shift;
+ p += i << shift;
+ p += (uintptr_t) pool->start;
+
+ goto done;
+ }
+ }
+
+ page = page->next;
+
+ } while (page);
+
+ } else { /* size < ngx_pagesize */
+
+ n = ngx_pagesize_shift - (page->slab & NGX_SLAB_SHIFT_MASK);
+ n = 1 << n;
+ n = (1 << n) - 1;
+ mask = n << NGX_SLAB_MAP_SHIFT;
+
+ do {
+ if ((page->slab & NGX_SLAB_MAP_MASK) != mask) {
+
+ for (m = 1 << NGX_SLAB_MAP_SHIFT, i = 0;
+ m & mask;
+ m <<= 1, i++)
+ {
+ if ((page->slab & m)) {
+ continue;
+ }
+
+ page->slab |= m;
+
+ if ((page->slab & NGX_SLAB_MAP_MASK) == mask) {
+ prev = (ngx_slab_page_t *)
+ (page->prev & ~NGX_SLAB_PAGE_MASK);
+ prev->next = page->next;
+ page->next->prev = page->prev;
+
+ page->next = NULL;
+ page->prev = NGX_SLAB_BIG;
+ }
+
+ p = (page - pool->pages) << ngx_pagesize_shift;
+ p += i << shift;
+ p += (uintptr_t) pool->start;
+
+ goto done;
+ }
+ }
+
+ page = page->next;
+
+ } while (page);
+ }
+ }
+
+ page = ngx_slab_alloc_pages(pool, 1);
+
+ if (page) {
+ if (size < ngx_slab_exact_size) {
+ p = (page - pool->pages) << ngx_pagesize_shift;
+ bitmap = (uintptr_t *) (pool->start + p);
+
+ s = 1 << shift;
+ n = (1 << (ngx_pagesize_shift - shift)) / 8 / s;
+
+ if (n == 0) {
+ n = 1;
+ }
+
+ bitmap[0] = (2 << n) - 1;
+
+ map = (1 << (ngx_pagesize_shift - shift)) / (sizeof(uintptr_t) * 8);
+
+ for (i = 1; i < map; i++) {
+ bitmap[i] = 0;
+ }
+
+ page->slab = shift;
+ page->next = &slots[slot];
+ page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_SMALL;
+
+ slots[slot].next = page;
+
+ p = ((page - pool->pages) << ngx_pagesize_shift) + s * n;
+ p += (uintptr_t) pool->start;
+
+ goto done;
+
+ } else if (size == ngx_slab_exact_size) {
+
+ page->slab = 1;
+ page->next = &slots[slot];
+ page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_EXACT;
+
+ slots[slot].next = page;
+
+ p = (page - pool->pages) << ngx_pagesize_shift;
+ p += (uintptr_t) pool->start;
+
+ goto done;
+
+ } else { /* size < ngx_pagesize */
+
+ page->slab = (1 << NGX_SLAB_MAP_SHIFT) | shift;
+ page->next = &slots[slot];
+ page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_BIG;
+
+ slots[slot].next = page;
+
+ p = (page - pool->pages) << ngx_pagesize_shift;
+ p += (uintptr_t) pool->start;
+
+ goto done;
+ }
+ }
+
+ p = 0;
+
+done:
+
+ ngx_shmtx_unlock(&pool->mutex);
+
+ ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, "slab alloc: %p", p);
+
+ return (void *) p;
+}
+
+
+void
+ngx_slab_free(ngx_slab_pool_t *pool, void *p)
+{
+ size_t size;
+ uintptr_t slab, *bitmap;
+ ngx_uint_t n, m, type, slot, shift, map;
+ ngx_slab_page_t *slots, *page;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, "slab free: %p", p);
+
+ ngx_shmtx_lock(&pool->mutex);
+
+ if ((u_char *) p < pool->start || (u_char *) p > pool->end) {
+ ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
+ "ngx_slab_free(): outside of pool");
+ goto fail;
+ }
+
+ n = ((u_char *) p - pool->start) >> ngx_pagesize_shift;
+ page = &pool->pages[n];
+ slab = page->slab;
+ type = page->prev & NGX_SLAB_PAGE_MASK;
+
+ switch (type) {
+
+ case NGX_SLAB_SMALL:
+
+ shift = slab & NGX_SLAB_SHIFT_MASK;
+ size = 1 << shift;
+
+ if ((uintptr_t) p & (size - 1)) {
+ goto wrong_chunk;
+ }
+
+ n = ((uintptr_t) p & (ngx_pagesize - 1)) >> shift;
+ m = 1 << (n & (sizeof(uintptr_t) * 8 - 1));
+ n /= (sizeof(uintptr_t) * 8);
+ bitmap = (uintptr_t *) ((uintptr_t) p & ~(ngx_pagesize - 1));
+
+ if (bitmap[n] & m) {
+
+ if (page->next == NULL) {
+ slots = (ngx_slab_page_t *)
+ ((u_char *) pool + sizeof(ngx_slab_pool_t));
+ slot = shift - pool->min_shift;
+
+ page->next = slots[slot].next;
+ slots[slot].next = page;
+
+ page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_SMALL;
+ page->next->prev = (uintptr_t) page | NGX_SLAB_SMALL;
+ }
+
+ bitmap[n] &= ~m;
+
+ n = (1 << (ngx_pagesize_shift - shift)) / 8 / (1 << shift);
+
+ if (n == 0) {
+ n = 1;
+ }
+
+ if (bitmap[0] & ~((1 << n) - 1)) {
+ goto done;
+ }
+
+ map = (1 << (ngx_pagesize_shift - shift)) / (sizeof(uintptr_t) * 8);
+
+ for (n = 1; n < map; n++) {
+ if (bitmap[n]) {
+ goto done;
+ }
+ }
+
+ ngx_slab_free_pages(pool, page, 1);
+
+ goto done;
+ }
+
+ goto chunk_already_free;
+
+ case NGX_SLAB_EXACT:
+
+ m = 1 << (((uintptr_t) p & (ngx_pagesize - 1)) >> ngx_slab_exact_shift);
+ size = ngx_slab_exact_size;
+
+ if ((uintptr_t) p & (size - 1)) {
+ goto wrong_chunk;
+ }
+
+ if (slab & m) {
+ if (slab == NGX_SLAB_BUSY) {
+ slots = (ngx_slab_page_t *)
+ ((u_char *) pool + sizeof(ngx_slab_pool_t));
+ slot = ngx_slab_exact_shift - pool->min_shift;
+
+ page->next = slots[slot].next;
+ slots[slot].next = page;
+
+ page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_EXACT;
+ page->next->prev = (uintptr_t) page | NGX_SLAB_EXACT;
+ }
+
+ page->slab &= ~m;
+
+ if (page->slab) {
+ goto done;
+ }
+
+ ngx_slab_free_pages(pool, page, 1);
+
+ goto done;
+ }
+
+ goto chunk_already_free;
+
+ case NGX_SLAB_BIG:
+
+ shift = slab & NGX_SLAB_SHIFT_MASK;
+ size = 1 << shift;
+
+ if ((uintptr_t) p & (size - 1)) {
+ goto wrong_chunk;
+ }
+
+ m = 1 << ((((uintptr_t) p & (ngx_pagesize - 1)) >> shift)
+ + NGX_SLAB_MAP_SHIFT);
+
+ if (slab & m) {
+
+ if (page->next == NULL) {
+ slots = (ngx_slab_page_t *)
+ ((u_char *) pool + sizeof(ngx_slab_pool_t));
+ slot = shift - pool->min_shift;
+
+ page->next = slots[slot].next;
+ slots[slot].next = page;
+
+ page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_BIG;
+ page->next->prev = (uintptr_t) page | NGX_SLAB_BIG;
+ }
+
+ page->slab &= ~m;
+
+ if (page->slab & NGX_SLAB_MAP_MASK) {
+ goto done;
+ }
+
+ ngx_slab_free_pages(pool, page, 1);
+
+ goto done;
+ }
+
+ goto chunk_already_free;
+
+ case NGX_SLAB_PAGE:
+
+ if ((uintptr_t) p & (ngx_pagesize - 1)) {
+ goto wrong_chunk;
+ }
+
+ if (slab == NGX_SLAB_PAGE_FREE) {
+ ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
+ "ngx_slab_free(): page is already free");
+ goto fail;
+ }
+
+ if (slab == NGX_SLAB_PAGE_BUSY) {
+ ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
+ "ngx_slab_free(): pointer to wrong page");
+ goto fail;
+ }
+
+ n = ((u_char *) p - pool->start) >> ngx_pagesize_shift;
+ size = slab & ~NGX_SLAB_PAGE_START;
+
+ ngx_slab_free_pages(pool, &pool->pages[n], size);
+
+ size <<= ngx_pagesize_shift;
+
+ goto done;
+ }
+
+ /* not reached */
+
+ return;
+
+done:
+
+ ngx_slab_junk(p, size);
+
+ ngx_shmtx_unlock(&pool->mutex);
+
+ return;
+
+wrong_chunk:
+
+ ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
+ "ngx_slab_free(): pointer to wrong chunk");
+
+ goto fail;
+
+chunk_already_free:
+
+ ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
+ "ngx_slab_free(): chunk is already free");
+
+fail:
+
+ ngx_shmtx_unlock(&pool->mutex);
+
+ return;
+}
+
+
+static ngx_slab_page_t *
+ngx_slab_alloc_pages(ngx_slab_pool_t *pool, ngx_uint_t pages)
+{
+ ngx_slab_page_t *page, *p;
+
+ for (page = pool->free.next; page != &pool->free; page = page->next) {
+
+ if (page->slab >= pages) {
+
+ if (page->slab > pages) {
+ page[pages].slab = page->slab - pages;
+ page[pages].next = page->next;
+ page[pages].prev = page->prev;
+
+ p = (ngx_slab_page_t *) page->prev;
+ p->next = &page[pages];
+ page->next->prev = (uintptr_t) &page[pages];
+
+ } else {
+ p = (ngx_slab_page_t *) page->prev;
+ p->next = page->next;
+ page->next->prev = page->prev;
+ }
+
+ page->slab = pages | NGX_SLAB_PAGE_START;
+
+#if (NGX_DEBUG)
+ page->next = NULL;
+ page->prev = NGX_SLAB_PAGE;
+#endif
+
+ if (--pages == 0) {
+ return page;
+ }
+
+ for (p = page + 1; pages; pages--) {
+ p->slab = NGX_SLAB_PAGE_BUSY;
+#if (NGX_DEBUG)
+ p->next = NULL;
+ p->prev = NGX_SLAB_PAGE;
+#endif
+ p++;
+ }
+
+ return page;
+ }
+ }
+
+ ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, NGX_ENOMEM,
+ "ngx_slab_alloc(): failed");
+ return NULL;
+}
+
+
+static void
+ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page,
+ ngx_uint_t pages)
+{
+ ngx_slab_page_t *prev;
+
+ page->slab = pages--;
+
+ if (pages) {
+ ngx_memzero(&page[1], pages * sizeof(ngx_slab_page_t));
+ }
+
+ prev = (ngx_slab_page_t *) (page->prev & ~NGX_SLAB_PAGE_MASK);
+ prev->next = page->next;
+
+ page->next = pool->free.next;
+ pool->free.next = page;
+
+ page->prev = page->next->prev;
+ page->next->prev = (uintptr_t) page;
+}
diff --git a/src/core/ngx_slab.h b/src/core/ngx_slab.h
new file mode 100644
index 000000000..ea9e0ea25
--- /dev/null
+++ b/src/core/ngx_slab.h
@@ -0,0 +1,45 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#ifndef _NGX_SLAB_H_INCLUDED_
+#define _NGX_SLAB_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+typedef struct ngx_slab_page_s ngx_slab_page_t;
+
+struct ngx_slab_page_s {
+ uintptr_t slab;
+ ngx_slab_page_t *next;
+ uintptr_t prev;
+};
+
+
+typedef struct {
+ ngx_atomic_t lock;
+
+ size_t min_size;
+ size_t min_shift;
+
+ ngx_slab_page_t *pages;
+ ngx_slab_page_t free;
+
+ u_char *start;
+ u_char *end;
+
+ ngx_shmtx_t mutex;
+} ngx_slab_pool_t;
+
+
+void ngx_slab_init(ngx_slab_pool_t *pool);
+void *ngx_slab_alloc(ngx_slab_pool_t *pool, size_t size);
+void ngx_slab_free(ngx_slab_pool_t *pool, void *p);
+
+
+#endif /* _NGX_SLAB_H_INCLUDED_ */
diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c
index 66baf1aec..563186e3e 100644
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -483,18 +483,7 @@ ngx_event_module_init(ngx_cycle_t *cycle)
return NGX_OK;
}
-
if (ngx_accept_mutex_ptr) {
-
- /* reinit ngx_accept_mutex */
-
- if (ngx_shmtx_create(&ngx_accept_mutex, (void *) ngx_accept_mutex_ptr,
- ccf->lock_file.data, cycle->log)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
return NGX_OK;
}
@@ -528,8 +517,7 @@ ngx_event_module_init(ngx_cycle_t *cycle)
ngx_accept_mutex_ptr = (ngx_atomic_t *) shared;
- if (ngx_shmtx_create(&ngx_accept_mutex, shared, ccf->lock_file.data,
- cycle->log)
+ if (ngx_shmtx_create(&ngx_accept_mutex, shared, cycle->lock_file.data)
!= NGX_OK)
{
return NGX_ERROR;
@@ -596,7 +584,7 @@ ngx_event_process_init(ngx_cycle_t *cycle)
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
- if (ccf->worker_processes > 1 && ecf->accept_mutex) {
+ if (ccf->master && ccf->worker_processes > 1 && ecf->accept_mutex) {
ngx_use_accept_mutex = 1;
ngx_accept_mutex_held = 0;
ngx_accept_mutex_delay = ecf->accept_mutex_delay;
diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c
index bb371691b..59b89b0f9 100644
--- a/src/event/ngx_event_pipe.c
+++ b/src/event/ngx_event_pipe.c
@@ -295,6 +295,7 @@ ngx_event_pipe_read_upstream(ngx_event_pipe_t *p)
p->read_length += n;
cl = chain;
+ p->free_raw_bufs = NULL;
while (cl && n > 0) {
@@ -322,7 +323,12 @@ ngx_event_pipe_read_upstream(ngx_event_pipe_t *p)
}
}
- p->free_raw_bufs = cl;
+ if (cl) {
+ for (ln = cl; ln->next; ln = ln->next) { /* void */ }
+
+ ln->next = p->free_raw_bufs;
+ p->free_raw_bufs = cl;
+ }
}
#if (NGX_DEBUG)
diff --git a/src/event/ngx_event_timer.c b/src/event/ngx_event_timer.c
index 3eb23f6d3..ababb819a 100644
--- a/src/event/ngx_event_timer.c
+++ b/src/event/ngx_event_timer.c
@@ -23,6 +23,7 @@ ngx_event_timer_init(ngx_log_t *log)
{
ngx_event_timer_rbtree.root = &ngx_event_timer_sentinel;
ngx_event_timer_rbtree.sentinel = &ngx_event_timer_sentinel;
+ ngx_event_timer_rbtree.insert = ngx_rbtree_insert_timer_value;
#if (NGX_THREADS)
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index dc511d8f7..f7bd5877e 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -17,7 +17,7 @@ our @EXPORT = qw(
HTTP_SERVER_ERROR
);
-our $VERSION = '0.4.13';
+our $VERSION = '0.4.14';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs
index 90b4c57a9..8f1854b3b 100644
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -4,8 +4,6 @@
*/
-#define PERL_NO_GET_CONTEXT
-
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c
index 4fd19485f..e460550d7 100644
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -11,12 +11,8 @@
typedef struct {
- PerlInterpreter **free_perls;
- ngx_uint_t interp;
- ngx_uint_t nalloc;
- ngx_uint_t interp_max;
-
PerlInterpreter *perl;
+ HV *nginx;
ngx_str_t modules;
ngx_array_t requires;
} ngx_http_perl_main_conf_t;
@@ -45,12 +41,6 @@ static ngx_int_t ngx_http_perl_ssi(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ssi_ctx, ngx_str_t **params);
#endif
-static ngx_int_t
- ngx_http_perl_get_interpreter(ngx_http_perl_main_conf_t *pmcf,
- PerlInterpreter **perl, ngx_log_t *log);
-static ngx_inline void
- ngx_http_perl_free_interpreter(ngx_http_perl_main_conf_t *pmcf,
- PerlInterpreter *perl);
static char *ngx_http_perl_init_interpreter(ngx_conf_t *cf,
ngx_http_perl_main_conf_t *pmcf);
static PerlInterpreter *
@@ -59,7 +49,7 @@ static PerlInterpreter *
static ngx_int_t ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires,
ngx_log_t *log);
static ngx_int_t ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r,
- SV *sub, ngx_str_t **args, ngx_str_t *handler, ngx_str_t *rv);
+ HV *nginx, SV *sub, ngx_str_t **args, ngx_str_t *handler, ngx_str_t *rv);
static void ngx_http_perl_eval_anon_sub(pTHX_ ngx_str_t *handler, SV **sv);
static ngx_int_t ngx_http_perl_preconfiguration(ngx_conf_t *cf);
@@ -72,16 +62,11 @@ static char *ngx_http_perl_require(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-static char *ngx_http_perl_interp_max_unsupported(ngx_conf_t *cf, void *post,
- void *data);
-#if (NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY)
-static void ngx_http_perl_cleanup_perl(void *data);
-#endif
static void ngx_http_perl_cleanup_sv(void *data);
-
-static ngx_conf_post_handler_pt ngx_http_perl_interp_max_p =
- ngx_http_perl_interp_max_unsupported;
+#if (NGX_HAVE_PERL_MULTIPLICITY)
+static void ngx_http_perl_cleanup_perl(void *data);
+#endif
static ngx_command_t ngx_http_perl_commands[] = {
@@ -100,13 +85,6 @@ static ngx_command_t ngx_http_perl_commands[] = {
0,
NULL },
- { ngx_string("perl_interp_max"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_MAIN_CONF_OFFSET,
- offsetof(ngx_http_perl_main_conf_t, interp_max),
- &ngx_http_perl_interp_max_p },
-
{ ngx_string("perl"),
NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_http_perl,
@@ -200,24 +178,6 @@ ngx_http_perl_handler(ngx_http_request_t *r)
ngx_http_perl_handle_request(r);
return NGX_DONE;
-
-#if 0
- r->request_body_in_single_buf = 1;
- r->request_body_in_persistent_file = 1;
- r->request_body_delete_incomplete_file = 1;
-
- if (r->request_body_in_file_only) {
- r->request_body_file_log_level = 0;
- }
-
- rc = ngx_http_read_client_request_body(r, ngx_http_perl_handle_request);
-
- if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
- return rc;
- }
-
- return NGX_DONE;
-#endif
}
@@ -247,16 +207,10 @@ ngx_http_perl_handle_request(ngx_http_request_t *r)
pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
- rc = ngx_http_perl_get_interpreter(pmcf, &ctx->perl, r->connection->log);
-
- if (rc != NGX_OK) {
- ngx_http_finalize_request(r, rc);
- return;
- }
-
{
- dTHXa(ctx->perl);
+ dTHXa(pmcf->perl);
+ PERL_SET_CONTEXT(pmcf->perl);
if (ctx->next == NULL) {
plcf = ngx_http_get_module_loc_conf(r, ngx_http_perl_module);
@@ -269,12 +223,11 @@ ngx_http_perl_handle_request(ngx_http_request_t *r)
ctx->next = NULL;
}
- rc = ngx_http_perl_call_handler(aTHX_ r, sub, NULL, handler, NULL);
+ rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, sub, NULL, handler,
+ NULL);
}
- ngx_http_perl_free_interpreter(pmcf, ctx->perl);
-
if (rc > 600) {
rc = NGX_OK;
}
@@ -338,25 +291,18 @@ ngx_http_perl_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
- rc = ngx_http_perl_get_interpreter(pmcf, &ctx->perl, r->connection->log);
-
- if (rc != NGX_OK) {
- return rc;
- }
-
value.data = NULL;
{
- dTHXa(ctx->perl);
+ dTHXa(pmcf->perl);
+ PERL_SET_CONTEXT(pmcf->perl);
- rc = ngx_http_perl_call_handler(aTHX_ r, pv->sub, NULL,
+ rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, pv->sub, NULL,
&pv->handler, &value);
}
- ngx_http_perl_free_interpreter(pmcf, ctx->perl);
-
if (value.data) {
v->len = value.len;
v->valid = 1;
@@ -371,6 +317,9 @@ ngx_http_perl_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
ctx->filename.data = NULL;
ctx->redirect_uri.len = 0;
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "perl variable done");
+
return rc;
}
@@ -390,8 +339,6 @@ ngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx,
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"perl ssi handler");
- pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
-
ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
if (ctx == NULL) {
@@ -403,11 +350,7 @@ ngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx,
ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
}
- rc = ngx_http_perl_get_interpreter(pmcf, &ctx->perl, r->connection->log);
-
- if (rc != NGX_OK) {
- return rc;
- }
+ pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
ctx->ssi = ssi_ctx;
@@ -416,7 +359,8 @@ ngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx,
{
- dTHXa(ctx->perl);
+ dTHXa(pmcf->perl);
+ PERL_SET_CONTEXT(pmcf->perl);
#if 0
@@ -438,65 +382,30 @@ ngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx,
sv = newSVpvn((char *) handler->data, handler->len);
- rc = ngx_http_perl_call_handler(aTHX_ r, sv, &params[NGX_HTTP_PERL_SSI_ARG],
+ rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, sv,
+ &params[NGX_HTTP_PERL_SSI_ARG],
handler, NULL);
SvREFCNT_dec(sv);
}
- ngx_http_perl_free_interpreter(pmcf, ctx->perl);
-
ctx->filename.data = NULL;
ctx->redirect_uri.len = 0;
ctx->ssi = NULL;
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl ssi done");
+
return rc;
}
#endif
-static ngx_int_t
-ngx_http_perl_get_interpreter(ngx_http_perl_main_conf_t *pmcf,
- PerlInterpreter **perl, ngx_log_t *log)
-{
- if (pmcf->interp) {
- pmcf->interp--;
-
- *perl = pmcf->free_perls[pmcf->interp];
-
- return NGX_OK;
- }
-
- if (pmcf->nalloc < pmcf->interp_max) {
- *perl = ngx_http_perl_create_interpreter(pmcf, log);
-
- if (*perl) {
- return NGX_OK;
- }
-
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_log_error(NGX_LOG_ALERT, log, 0, "no free perl interpreter");
-
- return NGX_HTTP_SERVICE_UNAVAILABLE;
-}
-
-
-static ngx_inline void
-ngx_http_perl_free_interpreter(ngx_http_perl_main_conf_t *pmcf,
- PerlInterpreter *perl)
-{
- pmcf->free_perls[pmcf->interp++] = perl;
-}
-
-
static char *
ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf)
{
-#if (NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY)
+#if (NGX_HAVE_PERL_MULTIPLICITY)
ngx_pool_cleanup_t *cln;
cln = ngx_pool_cleanup_add(cf->pool, 0);
@@ -520,7 +429,7 @@ ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf)
}
}
-#if !(NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY)
+#if !(NGX_HAVE_PERL_MULTIPLICITY)
if (perl) {
if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, cf->log)
@@ -545,7 +454,9 @@ ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf)
return NGX_CONF_ERROR;
}
-#if (NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY)
+ pmcf->nginx = nginx_stash;
+
+#if (NGX_HAVE_PERL_MULTIPLICITY)
cln->handler = ngx_http_perl_cleanup_perl;
cln->data = pmcf->perl;
@@ -572,43 +483,18 @@ ngx_http_perl_create_interpreter(ngx_http_perl_main_conf_t *pmcf,
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "create perl interpreter");
-#if (NGX_HAVE_PERL_CLONE)
-
- if (pmcf->perl) {
-
- perl = perl_clone(pmcf->perl, CLONEf_KEEP_PTR_TABLE);
- if (perl == NULL) {
- ngx_log_error(NGX_LOG_ALERT, log, 0, "perl_clone() failed");
- return NULL;
- }
-
- {
-
- dTHXa(perl);
-
- ptr_table_free(PL_ptr_table);
- PL_ptr_table = NULL;
-
- }
-
- pmcf->nalloc++;
-
- return perl;
- }
-
-#endif
-
perl = perl_alloc();
if (perl == NULL) {
ngx_log_error(NGX_LOG_ALERT, log, 0, "perl_alloc() failed");
return NULL;
}
- perl_construct(perl);
-
{
dTHXa(perl);
+ PERL_SET_CONTEXT(perl);
+
+ perl_construct(perl);
#ifdef PERL_EXIT_DESTRUCT_END
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
@@ -652,8 +538,6 @@ ngx_http_perl_create_interpreter(ngx_http_perl_main_conf_t *pmcf,
}
- pmcf->nalloc++;
-
return perl;
fail:
@@ -699,7 +583,7 @@ ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires, ngx_log_t *log)
static ngx_int_t
-ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r, SV *sub,
+ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r, HV *nginx, SV *sub,
ngx_str_t **args, ngx_str_t *handler, ngx_str_t *rv)
{
SV *sv;
@@ -718,7 +602,7 @@ ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r, SV *sub,
PUSHMARK(sp);
- sv = sv_2mortal(sv_bless(newRV_noinc(newSViv(PTR2IV(r))), nginx_stash));
+ sv = sv_2mortal(sv_bless(newRV_noinc(newSViv(PTR2IV(r))), nginx));
XPUSHs(sv);
if (args) {
@@ -810,6 +694,9 @@ ngx_http_perl_eval_anon_sub(pTHX_ ngx_str_t *handler, SV **sv)
if (ngx_strncmp(p, "sub ", 4) == 0 || ngx_strncmp(p, "use ", 4) == 0) {
*sv = eval_pv((char *) p, FALSE);
+
+ /* eval_pv() does not set ERRSV on failure */
+
return;
}
@@ -827,8 +714,6 @@ ngx_http_perl_create_main_conf(ngx_conf_t *cf)
return NGX_CONF_ERROR;
}
- pmcf->interp_max = NGX_CONF_UNSET_UINT;
-
if (ngx_array_init(&pmcf->requires, cf->pool, 1, sizeof(u_char *))
!= NGX_OK)
{
@@ -844,39 +729,25 @@ ngx_http_perl_init_main_conf(ngx_conf_t *cf, void *conf)
{
ngx_http_perl_main_conf_t *pmcf = conf;
-#if (NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY)
- ngx_conf_init_uint_value(pmcf->interp_max, 10);
-#else
- ngx_conf_init_uint_value(pmcf->interp_max, 1);
-#endif
-
- pmcf->free_perls = ngx_pcalloc(cf->pool,
- pmcf->interp_max * sizeof(PerlInterpreter *));
- if (pmcf->free_perls == NULL) {
- return NGX_CONF_ERROR;
- }
-
if (pmcf->perl == NULL) {
if (ngx_http_perl_init_interpreter(cf, pmcf) != NGX_CONF_OK) {
return NGX_CONF_ERROR;
}
}
-#if !(NGX_HAVE_PERL_CLONE)
- ngx_http_perl_free_interpreter(pmcf, pmcf->perl);
-#endif
-
return NGX_CONF_OK;
}
-#if (NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY)
+#if (NGX_HAVE_PERL_MULTIPLICITY)
static void
ngx_http_perl_cleanup_perl(void *data)
{
PerlInterpreter *perl = data;
+ PERL_SET_CONTEXT(perl);
+
(void) perl_destruct(perl);
perl_free(perl);
@@ -893,6 +764,7 @@ ngx_http_perl_cleanup_sv(void *data)
ngx_http_perl_cleanup_t *cln = data;
dTHXa(cln->perl);
+ PERL_SET_CONTEXT(cln->perl);
SvREFCNT_dec(cln->sv);
}
@@ -1019,6 +891,7 @@ ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
dTHXa(pmcf->perl);
+ PERL_SET_CONTEXT(pmcf->perl);
ngx_http_perl_eval_anon_sub(aTHX_ &value[1], &plcf->sub);
@@ -1101,6 +974,7 @@ ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
dTHXa(pmcf->perl);
+ PERL_SET_CONTEXT(pmcf->perl);
ngx_http_perl_eval_anon_sub(aTHX_ &value[2], &pv->sub);
@@ -1126,19 +1000,3 @@ ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_OK;
}
-
-
-static char *
-ngx_http_perl_interp_max_unsupported(ngx_conf_t *cf, void *post, void *data)
-{
-#if (NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY)
-
- return NGX_CONF_OK;
-
-#else
-
- return "to use perl_interp_max you have to build perl with "
- "-Dusemultiplicity or -Dusethreads options";
-
-#endif
-}
diff --git a/src/http/modules/perl/ngx_http_perl_module.h b/src/http/modules/perl/ngx_http_perl_module.h
index 5a3d5082a..af23f9ef7 100644
--- a/src/http/modules/perl/ngx_http_perl_module.h
+++ b/src/http/modules/perl/ngx_http_perl_module.h
@@ -20,8 +20,6 @@
typedef ngx_http_request_t *nginx;
typedef struct {
- PerlInterpreter *perl;
-
ngx_str_t filename;
ngx_str_t redirect_uri;
ngx_str_t redirect_args;
@@ -48,7 +46,7 @@ extern ngx_module_t ngx_http_perl_module;
#endif
-extern void boot_DynaLoader(pTHX_ CV* cv);
+extern void boot_DynaLoader(pTHX_ CV* cv);
void ngx_http_perl_handle_request(ngx_http_request_t *r);
diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c
index b9022bdce..b141000b6 100644
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -260,7 +260,7 @@ ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
case sw_schema_slash_slash:
switch (ch) {
case '/':
- r->host_start = p;
+ r->host_start = p + 1;
state = sw_host;
break;
default:
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 951db75e4..bbd025575 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1385,8 +1385,15 @@ ngx_http_find_virtual_server(ngx_http_request_t *r,
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_srv_conf_t *cscf;
- host = r->headers_in.host->value.data;
- len = r->headers_in.host_name_len;
+ host = r->host_start;
+
+ if (host == NULL) {
+ host = r->headers_in.host->value.data;
+ len = r->headers_in.host_name_len;
+
+ } else {
+ len = r->host_end - host;
+ }
if (vn->hash.buckets) {
cscf = ngx_hash_find(&vn->hash, hash, host, len);
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index b86f70128..f830236f4 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -512,6 +512,7 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
{
ngx_int_t rc;
ngx_time_t *tp;
+ ngx_msec_int_t ms;
ngx_connection_t *c;
r->connection->log->action = "connecting to upstream";
@@ -520,8 +521,8 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
if (u->state && u->state->response_time) {
tp = ngx_timeofday();
- u->state->response_time = tp->sec * 1000 + tp->msec
- - u->state->response_time;
+ ms = tp->sec * 1000 + tp->msec - u->state->response_time;
+ u->state->response_time = (ms >= 0) ? ms : 0;
}
u->state = ngx_array_push(&u->states);
@@ -2057,7 +2058,8 @@ static void
ngx_http_upstream_finalize_request(ngx_http_request_t *r,
ngx_http_upstream_t *u, ngx_int_t rc)
{
- ngx_time_t *tp;
+ ngx_time_t *tp;
+ ngx_msec_int_t ms;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"finalize http upstream request: %i", rc);
@@ -2066,8 +2068,8 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r,
if (u->state->response_time) {
tp = ngx_timeofday();
- u->state->response_time = tp->sec * 1000 + tp->msec
- - u->state->response_time;
+ ms = tp->sec * 1000 + tp->msec - u->state->response_time;
+ u->state->response_time = (ms >= 0) ? ms : 0;
}
u->finalize_request(r, rc);
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 120145829..c31defc4e 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -667,13 +667,20 @@ static ngx_int_t
ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v,
uintptr_t data)
{
- if (r->headers_in.host) {
- v->len = r->headers_in.host_name_len;
- v->data = r->headers_in.host->value.data;
+ if (r->host_start == NULL) {
+
+ if (r->headers_in.host) {
+ v->len = r->headers_in.host_name_len;
+ v->data = r->headers_in.host->value.data;
+
+ } else {
+ v->len = r->server_name.len;
+ v->data = r->server_name.data;
+ }
} else {
- v->len = r->server_name.len;
- v->data = r->server_name.data;
+ v->len = r->host_end - r->host_start;
+ v->data = r->host_start;
}
v->valid = 1;
diff --git a/src/imap/ngx_imap_auth_http_module.c b/src/imap/ngx_imap_auth_http_module.c
index 85728f46a..d39c29502 100644
--- a/src/imap/ngx_imap_auth_http_module.c
+++ b/src/imap/ngx_imap_auth_http_module.c
@@ -182,7 +182,10 @@ ngx_imap_auth_http_init(ngx_imap_session_t *s)
rc = ngx_event_connect_peer(&ctx->peer);
if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
- ngx_close_connection(ctx->peer.connection);
+ if (ctx->peer.connection) {
+ ngx_close_connection(ctx->peer.connection);
+ }
+
ngx_destroy_pool(ctx->pool);
ngx_imap_session_internal_server_error(s);
return;
@@ -489,10 +492,10 @@ ngx_imap_auth_http_process_headers(ngx_imap_session_t *s,
ctx->errmsg.data = ctx->header_start;
if (s->protocol == NGX_IMAP_POP3_PROTOCOL) {
- size = sizeof("-ERR") - 1 + len + sizeof(CRLF) - 1;
+ size = sizeof("-ERR ") - 1 + len + sizeof(CRLF) - 1;
} else {
- size = s->tag.len + sizeof("NO") - 1 + len
+ size = s->tag.len + sizeof("NO ") - 1 + len
+ sizeof(CRLF) - 1;
}
@@ -1039,7 +1042,9 @@ ngx_imap_auth_http_create_request(ngx_imap_session_t *s, ngx_pool_t *pool,
len = sizeof("GET ") - 1 + ahcf->uri.len + sizeof(" HTTP/1.0" CRLF) - 1
+ sizeof("Host: ") - 1 + ahcf->host_header.len + sizeof(CRLF) - 1
- + sizeof("Auth-Method: plain" CRLF) - 1
+ + sizeof("Auth-Method: ") - 1
+ + ngx_imap_auth_http_method[s->auth_method].len
+ + sizeof(CRLF) - 1
+ sizeof("Auth-User: ") - 1 + login.len + sizeof(CRLF) - 1
+ sizeof("Auth-Pass: ") - 1 + passwd.len + sizeof(CRLF) - 1
+ sizeof("Auth-Salt: ") - 1 + s->salt.len
diff --git a/src/imap/ngx_imap_handler.c b/src/imap/ngx_imap_handler.c
index 26513940b..2b3d29cbc 100644
--- a/src/imap/ngx_imap_handler.c
+++ b/src/imap/ngx_imap_handler.c
@@ -12,6 +12,7 @@
static void ngx_imap_init_session(ngx_connection_t *c);
static void ngx_imap_init_protocol(ngx_event_t *rev);
+static void ngx_imap_do_auth(ngx_imap_session_t *s);
static ngx_int_t ngx_imap_read_command(ngx_imap_session_t *s);
static u_char *ngx_imap_log_error(ngx_log_t *log, u_char *buf, size_t len);
@@ -537,18 +538,7 @@ ngx_imap_auth_state(ngx_event_t *rev)
"imap login:\"%V\"", &s->login);
#endif
- s->args.nelts = 0;
- s->buffer->pos = s->buffer->start;
- s->buffer->last = s->buffer->start;
-
- if (rev->timer_set) {
- ngx_del_timer(rev);
- }
-
- s->login_attempt++;
-
- ngx_imap_auth_http_init(s);
-
+ ngx_imap_do_auth(s);
return;
}
@@ -789,16 +779,7 @@ ngx_pop3_auth_state(ngx_event_t *rev)
s->auth_method = NGX_IMAP_AUTH_APOP;
- s->args.nelts = 0;
- s->buffer->pos = s->buffer->start;
- s->buffer->last = s->buffer->start;
-
- if (rev->timer_set) {
- ngx_del_timer(rev);
- }
-
- ngx_imap_auth_http_init(s);
-
+ ngx_imap_do_auth(s);
return;
}
@@ -922,16 +903,7 @@ ngx_pop3_auth_state(ngx_event_t *rev)
"pop3 passwd: \"%V\"", &s->passwd);
#endif
- s->args.nelts = 0;
- s->buffer->pos = s->buffer->start;
- s->buffer->last = s->buffer->start;
-
- if (rev->timer_set) {
- ngx_del_timer(rev);
- }
-
- ngx_imap_auth_http_init(s);
-
+ ngx_imap_do_auth(s);
return;
}
@@ -1021,16 +993,7 @@ ngx_pop3_auth_state(ngx_event_t *rev)
"pop3 auth login password: \"%V\"", &s->passwd);
#endif
- s->args.nelts = 0;
- s->buffer->pos = s->buffer->start;
- s->buffer->last = s->buffer->start;
-
- if (rev->timer_set) {
- ngx_del_timer(rev);
- }
-
- ngx_imap_auth_http_init(s);
-
+ ngx_imap_do_auth(s);
return;
case ngx_pop3_auth_plain:
@@ -1092,16 +1055,7 @@ ngx_pop3_auth_state(ngx_event_t *rev)
&s->login, &s->passwd);
#endif
- s->args.nelts = 0;
- s->buffer->pos = s->buffer->start;
- s->buffer->last = s->buffer->start;
-
- if (rev->timer_set) {
- ngx_del_timer(rev);
- }
-
- ngx_imap_auth_http_init(s);
-
+ ngx_imap_do_auth(s);
return;
case ngx_pop3_auth_cram_md5:
@@ -1151,16 +1105,7 @@ ngx_pop3_auth_state(ngx_event_t *rev)
s->auth_method = NGX_IMAP_AUTH_CRAM_MD5;
- s->args.nelts = 0;
- s->buffer->pos = s->buffer->start;
- s->buffer->last = s->buffer->start;
-
- if (rev->timer_set) {
- ngx_del_timer(rev);
- }
-
- ngx_imap_auth_http_init(s);
-
+ ngx_imap_do_auth(s);
return;
}
}
@@ -1187,6 +1132,24 @@ ngx_pop3_auth_state(ngx_event_t *rev)
}
+static void
+ngx_imap_do_auth(ngx_imap_session_t *s)
+{
+ s->args.nelts = 0;
+ s->buffer->pos = s->buffer->start;
+ s->buffer->last = s->buffer->start;
+ s->state = 0;
+
+ if (s->connection->read->timer_set) {
+ ngx_del_timer(s->connection->read);
+ }
+
+ s->login_attempt++;
+
+ ngx_imap_auth_http_init(s);
+}
+
+
static ngx_int_t
ngx_imap_read_command(ngx_imap_session_t *s)
{
diff --git a/src/imap/ngx_imap_proxy_module.c b/src/imap/ngx_imap_proxy_module.c
index 6ab225b0c..fd4e41b84 100644
--- a/src/imap/ngx_imap_proxy_module.c
+++ b/src/imap/ngx_imap_proxy_module.c
@@ -13,6 +13,7 @@
typedef struct {
ngx_flag_t enable;
+ ngx_flag_t pass_error_message;
size_t buffer_size;
ngx_msec_t timeout;
} ngx_imap_proxy_conf_t;
@@ -25,6 +26,7 @@ static void ngx_imap_proxy_dummy_handler(ngx_event_t *ev);
static ngx_int_t ngx_imap_proxy_read_response(ngx_imap_session_t *s,
ngx_uint_t state);
static void ngx_imap_proxy_handler(ngx_event_t *ev);
+static void ngx_imap_proxy_upstream_error(ngx_imap_session_t *s);
static void ngx_imap_proxy_internal_server_error(ngx_imap_session_t *s);
static void ngx_imap_proxy_close_session(ngx_imap_session_t *s);
static void *ngx_imap_proxy_create_conf(ngx_conf_t *cf);
@@ -55,6 +57,13 @@ static ngx_command_t ngx_imap_proxy_commands[] = {
offsetof(ngx_imap_proxy_conf_t, timeout),
NULL },
+ { ngx_string("proxy_pass_error_message"),
+ NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_flag_slot,
+ NGX_IMAP_SRV_CONF_OFFSET,
+ offsetof(ngx_imap_proxy_conf_t, pass_error_message),
+ NULL },
+
ngx_null_command
};
@@ -204,7 +213,7 @@ ngx_imap_proxy_imap_handler(ngx_event_t *rev)
}
if (rc == NGX_ERROR) {
- ngx_imap_proxy_internal_server_error(s);
+ ngx_imap_proxy_upstream_error(s);
return;
}
@@ -349,7 +358,7 @@ ngx_imap_proxy_pop3_handler(ngx_event_t *rev)
}
if (rc == NGX_ERROR) {
- ngx_imap_proxy_internal_server_error(s);
+ ngx_imap_proxy_upstream_error(s);
return;
}
@@ -452,9 +461,10 @@ ngx_imap_proxy_dummy_handler(ngx_event_t *wev)
static ngx_int_t
ngx_imap_proxy_read_response(ngx_imap_session_t *s, ngx_uint_t state)
{
- u_char *p;
- ssize_t n;
- ngx_buf_t *b;
+ u_char *p;
+ ssize_t n;
+ ngx_buf_t *b;
+ ngx_imap_proxy_conf_t *pcf;
s->connection->log->action = "reading response from upstream";
@@ -523,9 +533,23 @@ ngx_imap_proxy_read_response(ngx_imap_session_t *s, ngx_uint_t state)
}
}
- *(b->last - 2) = '\0';
- ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
- "upstream sent invalid response: \"%s\"", p);
+ pcf = ngx_imap_get_module_srv_conf(s, ngx_imap_proxy_module);
+
+ if (pcf->pass_error_message == 0) {
+ *(b->last - 2) = '\0';
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
+ "upstream sent invalid response: \"%s\"", p);
+ return NGX_ERROR;
+ }
+
+ s->out.len = b->last - p - 2;
+ s->out.data = p;
+
+ ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
+ "upstream sent invalid response: \"%V\"", &s->out);
+
+ s->out.len = b->last - b->pos;
+ s->out.data = b->pos;
return NGX_ERROR;
}
@@ -698,6 +722,27 @@ ngx_imap_proxy_handler(ngx_event_t *ev)
static void
+ngx_imap_proxy_upstream_error(ngx_imap_session_t *s)
+{
+ if (s->proxy->upstream.connection) {
+ ngx_log_debug1(NGX_LOG_DEBUG_IMAP, s->connection->log, 0,
+ "close imap proxy connection: %d",
+ s->proxy->upstream.connection->fd);
+
+ ngx_close_connection(s->proxy->upstream.connection);
+ }
+
+ if (s->out.len == 0) {
+ ngx_imap_session_internal_server_error(s);
+ return;
+ }
+
+ s->quit = 1;
+ ngx_imap_send(s->connection->write);
+}
+
+
+static void
ngx_imap_proxy_internal_server_error(ngx_imap_session_t *s)
{
if (s->proxy->upstream.connection) {
@@ -738,6 +783,7 @@ ngx_imap_proxy_create_conf(ngx_conf_t *cf)
}
pcf->enable = NGX_CONF_UNSET;
+ pcf->pass_error_message = NGX_CONF_UNSET;
pcf->buffer_size = NGX_CONF_UNSET_SIZE;
pcf->timeout = NGX_CONF_UNSET_MSEC;
@@ -752,6 +798,7 @@ ngx_imap_proxy_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_imap_proxy_conf_t *conf = child;
ngx_conf_merge_value(conf->enable, prev->enable, 0);
+ ngx_conf_merge_value(conf->pass_error_message, prev->pass_error_message, 0);
ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
(size_t) ngx_pagesize);
ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 24 * 60 * 60000);
diff --git a/src/os/unix/ngx_alloc.c b/src/os/unix/ngx_alloc.c
index 25606e2f6..c38d7d27e 100644
--- a/src/os/unix/ngx_alloc.c
+++ b/src/os/unix/ngx_alloc.c
@@ -8,7 +8,8 @@
#include <ngx_core.h>
-int ngx_pagesize;
+ngx_uint_t ngx_pagesize;
+ngx_uint_t ngx_pagesize_shift;
ngx_uint_t ngx_cacheline_size;
diff --git a/src/os/unix/ngx_alloc.h b/src/os/unix/ngx_alloc.h
index a88818e2e..8b7b766b2 100644
--- a/src/os/unix/ngx_alloc.h
+++ b/src/os/unix/ngx_alloc.h
@@ -36,7 +36,8 @@ void *ngx_memalign(size_t alignment, size_t size, ngx_log_t *log);
#endif
-extern int ngx_pagesize;
+extern ngx_uint_t ngx_pagesize;
+extern ngx_uint_t ngx_pagesize_shift;
extern ngx_uint_t ngx_cacheline_size;
diff --git a/src/os/unix/ngx_posix_init.c b/src/os/unix/ngx_posix_init.c
index 4844ae52f..39e1b584a 100644
--- a/src/os/unix/ngx_posix_init.c
+++ b/src/os/unix/ngx_posix_init.c
@@ -30,6 +30,8 @@ ngx_os_io_t ngx_os_io = {
ngx_int_t
ngx_os_init(ngx_log_t *log)
{
+ ngx_uint_t n;
+
#if (NGX_HAVE_OS_SPECIFIC_INIT)
if (ngx_os_specific_init(log) != NGX_OK) {
return NGX_ERROR;
@@ -41,6 +43,10 @@ ngx_os_init(ngx_log_t *log)
ngx_pagesize = getpagesize();
ngx_cacheline_size = NGX_CPU_CACHE_LINE;
+ n = ngx_pagesize;
+
+ for (n = ngx_pagesize; n >>= 1; ngx_pagesize_shift++) { /* void */ }
+
if (ngx_ncpu == 0) {
ngx_ncpu = 1;
}