# HG changeset patch # User Igor Sysoev # Date 1164574800 -10800 # Node ID 6ae1357b7b7cc70031807232df5de46ecf07f5bf # Parent 0e566ee1bcd53a08128002f254f1b62cb1046d6c nginx 0.4.14 *) Feature: the "proxy_pass_error_message" directive in IMAP/POP3 proxy. *) Feature: now configure detects system PCRE library on FreeBSD, Linux, and NetBSD. *) Bugfix: ngx_http_perl_module did not work with perl built with the threads support; bug appeared in 0.3.38. *) Bugfix: ngx_http_perl_module did not work if perl was called recursively. *) Bugfix: nginx ignored a host name in an request line. *) Bugfix: a worker process may got caught in an endless loop, if a FastCGI server sent too many data to the stderr. *) Bugfix: the $upstream_response_time variable may be negative if the system time was changed backward. *) 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. diff --git a/CHANGES b/CHANGES --- 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. - - *) Feature: the "limit_expect" directive supports all WebDAV methods. + "limit_except" block. + + *) 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 --- 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_expect поддерживает все WebDAV методы. + limit_except. + + *) Добавление: директива limit_except поддерживает все WebDAV методы. *) Исправление: при использовании директивы add_before_body без директивы add_after_body ответ передавался не полностью. diff --git a/auto/cc/conf b/auto/cc/conf --- 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 #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 #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 --- 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 --- 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 --- 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 @@ -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 --- 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 " + 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 " + 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 " - 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 " + 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 --- 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 " + 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 --- 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 " + 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 " + 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 " + 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 " + 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 --- 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 --- 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 " + 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 " - 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 " + 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 --- 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 " + 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 --- 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 " +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 " +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 " + 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 " + 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 #include " + 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 #include " + 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 --- 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 " +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 #include " +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 #include " +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 " +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 " +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 --- 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 " +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 " +ngx_feature_path= ngx_feature_libs= ngx_feature_test="int n = port_create()" . auto/feature diff --git a/auto/sources b/auto/sources --- 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 --- 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 " +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 " +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 " +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 " +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 " +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 " +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 " +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 #include #include " +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 #include " +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 " +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 $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 " +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 --- 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 bin exe dll; application/octet-stream deb; - application/octet-stream bin exe dll; 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-mng mng; video/x-ms-asf asx asf; - video/x-mng mng; + video/x-ms-wmv wmv; + video/x-msvideo avi; } diff --git a/src/core/nginx.c b/src/core/nginx.c --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -621,6 +621,7 @@ ngx_core_module_init_conf(ngx_cycle_t *c 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 *c 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 *c 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 --- 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 --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h @@ -64,6 +64,7 @@ typedef void (*ngx_connection_handler_pt #include #include #include +#include #if (NGX_OPENSSL) #include #endif diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c --- 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 --- 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 --- 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_e #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 --- a/src/core/ngx_log.h +++ b/src/core/ngx_log.h @@ -201,6 +201,7 @@ void ngx_cdecl ngx_log_debug_core(ngx_lo 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 --- a/src/core/ngx_palloc.c +++ b/src/core/ngx_palloc.c @@ -193,46 +193,6 @@ ngx_pcalloc(ngx_pool_t *pool, size_t siz } -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 --- a/src/core/ngx_palloc.h +++ b/src/core/ngx_palloc.h @@ -71,10 +71,6 @@ void *ngx_palloc(ngx_pool_t *pool, 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 --- a/src/core/ngx_rbtree.c +++ b/src/core/ngx_rbtree.c @@ -47,53 +47,10 @@ ngx_rbtree_insert(ngx_thread_volatile ng 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 ng ngx_rbtree_left_rotate(root, sentinel, node->parent->parent); } } - } ngx_rbt_black(*root); @@ -144,10 +100,86 @@ ngx_rbtree_insert(ngx_thread_volatile ng 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 ng 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 ng node->key = 0; } - if (is_red) { + if (red) { return; } diff --git a/src/core/ngx_rbtree.h b/src/core/ngx_rbtree.h --- 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_volati 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 --- 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 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 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 --- 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 --- /dev/null +++ b/src/core/ngx_slab.c @@ -0,0 +1,685 @@ + +/* + * Copyright (C) Igor Sysoev + */ + +#include +#include + +/* + + 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 --- /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 +#include + + +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 --- 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 *cycl 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 --- 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_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_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 --- 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 --- 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 --- a/src/http/modules/perl/nginx.xs +++ b/src/http/modules/perl/nginx.xs @@ -4,8 +4,6 @@ */ -#define PERL_NO_GET_CONTEXT - #include #include #include diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c --- 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_h 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_c 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_sv(void *data); + +#if (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; static ngx_command_t ngx_http_perl_commands[] = { @@ -100,13 +85,6 @@ static ngx_command_t ngx_http_perl_comm 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 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_re 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_re 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_ 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_ 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_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_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, { - 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, sv = newSVpvn((char *) handler->data, handler->len); - rc = ngx_http_perl_call_handler(aTHX_ r, sv, ¶ms[NGX_HTTP_PERL_SSI_ARG], + rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, sv, + ¶ms[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_ } } -#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_ 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_htt 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_htt } - pmcf->nalloc++; - return perl; fail: @@ -699,7 +583,7 @@ ngx_http_perl_run_requires(pTHX_ ngx_arr 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_htt 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_st 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_ 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 { 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_comman { 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_co { 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_co 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 --- 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_modul #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 --- 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_req 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 --- 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_re 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 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -512,6 +512,7 @@ ngx_http_upstream_connect(ngx_http_reque { 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_reque 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_h 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 --- 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 --- 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 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_i 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_im 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 --- 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 --- 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 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_com 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 } 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 } 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 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_se } } - *(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 *c } 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 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 --- a/src/os/unix/ngx_alloc.c +++ b/src/os/unix/ngx_alloc.c @@ -8,7 +8,8 @@ #include -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 --- a/src/os/unix/ngx_alloc.h +++ b/src/os/unix/ngx_alloc.h @@ -36,7 +36,8 @@ void *ngx_memalign(size_t alignment, siz #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 --- 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; }