view auto/unix @ 6891:749bcfdf097a stable-1.10

HTTP/2: fixed posted streams handling. A bug was introduced by 82efcedb310b that could lead to timing out of responses or segmentation fault, when accept_mutex was enabled. The output queue in HTTP/2 can contain frames from different streams. When the queue is sent, all related write handlers need to be called. In order to do so, the streams were added to the h2c->posted queue after handling sent frames. Then this queue was processed in ngx_http_v2_write_handler(). If accept_mutex is enabled, the event's "ready" flag is set but its handler is not called immediately. Instead, the event is added to the ngx_posted_events queue. At the same time in this queue can be events from upstream connections. Such events can result in sending output queue before ngx_http_v2_write_handler() is triggered. And at the time ngx_http_v2_write_handler() is called, the output queue can be already empty with some streams added to h2c->posted. But after 82efcedb310b, these streams weren't processed if all frames have already been sent and the output queue was empty. This might lead to a situation when a number of streams were get stuck in h2c->posted queue for a long time. Eventually these streams might get closed by the send timeout. In the worst case this might also lead to a segmentation fault, if already freed stream was left in the h2c->posted queue. This could happen if one of the streams was terminated but wasn't closed, due to the HEADERS frame or a partially sent DATA frame left in the output queue. If this happened the ngx_http_v2_filter_cleanup() handler removed the stream from the h2c->waiting or h2c->posted queue on termination stage, before the frame has been sent, and the stream was again added to the h2c->posted queue after the frame was sent. In order to fix all these problems and simplify the code, write events of fake stream connections are now added to ngx_posted_events instead of using a custom h2c->posted queue.
author Valentin Bartenev <vbart@nginx.com>
date Mon, 28 Nov 2016 20:58:14 +0300
parents 8426275a13fd
children 1d0e03db9f8e
line wrap: on
line source


# Copyright (C) Igor Sysoev
# Copyright (C) Nginx, Inc.


NGX_USER=${NGX_USER:-nobody}

if [ -z "$NGX_GROUP" ]; then
    if [ $NGX_USER = nobody ]; then
        if grep nobody /etc/group 2>&1 >/dev/null; then
            echo "checking for nobody group ... found"
            NGX_GROUP=nobody
        else
            echo "checking for nobody group ... not found"

            if grep nogroup /etc/group 2>&1 >/dev/null; then
                echo "checking for nogroup group ... found"
                NGX_GROUP=nogroup
            else
                echo "checking for nogroup group ... not found"
                NGX_GROUP=nobody
            fi
        fi
    else
        NGX_GROUP=$NGX_USER
    fi
fi


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; struct pollfd  pl;
                  pl.fd = 0;
                  pl.events = 0;
                  pl.revents = 0;
                  n = poll(&pl, 1, 0);
                  if (n == -1) return 1"
. auto/feature

if [ $ngx_found = no ]; then
    EVENT_POLL=NONE
fi


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;
                  dvp.dp_fds = NULL;
                  dvp.dp_nfds = 0;
                  dvp.dp_timeout = 0;
                  n = ioctl(dp, DP_POLL, &dvp);
                  if (n == -1) return 1"
. auto/feature

if [ $ngx_found = yes ]; then
    CORE_SRCS="$CORE_SRCS $DEVPOLL_SRCS"
    EVENT_MODULES="$EVENT_MODULES $DEVPOLL_MODULE"
    EVENT_FOUND=YES
fi


if test -z "$NGX_KQUEUE_CHECKED"; then
    ngx_feature="kqueue"
    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

    if [ $ngx_found = yes ]; then

        have=NGX_HAVE_CLEAR_EVENT . auto/have
        EVENT_MODULES="$EVENT_MODULES $KQUEUE_MODULE"
        CORE_SRCS="$CORE_SRCS $KQUEUE_SRCS"
        EVENT_FOUND=YES

        ngx_feature="kqueue's NOTE_LOWAT"
        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;"
        . auto/feature


        ngx_feature="kqueue's EVFILT_TIMER"
        ngx_feature_name="NGX_HAVE_TIMER_EVENT"
        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;
                  struct timespec  ts;

                  if ((kq = kqueue()) == -1) return 1;

                  kev.ident = 0;
                  kev.filter = EVFILT_TIMER;
                  kev.flags = EV_ADD|EV_ENABLE;
                  kev.fflags = 0;
                  kev.data = 1000;
                  kev.udata = 0;

                  ts.tv_sec = 0;
                  ts.tv_nsec = 0;

                  if (kevent(kq, &kev, 1, &kev, 1, &ts) == -1) return 1;

                  if (kev.flags & EV_ERROR) return 1;"

        . auto/feature
    fi
fi


if [ "$NGX_SYSTEM" = "NetBSD" ]; then

    # NetBSD 2.0 incompatibly defines kevent.udata as "intptr_t"

    cat << END >> $NGX_AUTO_CONFIG_H

#define NGX_KQUEUE_UDATA_T

END

else
    cat << END >> $NGX_AUTO_CONFIG_H

#define NGX_KQUEUE_UDATA_T  (void *)

END

fi


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


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

    if [ $ngx_found = yes ]; then
        CRYPT_LIB="-lcrypt"
    fi
fi


ngx_feature="F_READAHEAD"
ngx_feature_name="NGX_HAVE_F_READAHEAD"
ngx_feature_run=no
ngx_feature_incs="#include <fcntl.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="fcntl(0, F_READAHEAD, 1);"
. auto/feature


ngx_feature="posix_fadvise()"
ngx_feature_name="NGX_HAVE_POSIX_FADVISE"
ngx_feature_run=no
ngx_feature_incs="#include <fcntl.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="posix_fadvise(0, 0, 0, POSIX_FADV_SEQUENTIAL);"
. auto/feature


ngx_feature="O_DIRECT"
ngx_feature_name="NGX_HAVE_O_DIRECT"
ngx_feature_run=no
ngx_feature_incs="#include <fcntl.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="fcntl(0, F_SETFL, O_DIRECT);"
. auto/feature


if [ $ngx_found = yes -a "$NGX_SYSTEM" = "Linux" ]; then
    have=NGX_HAVE_ALIGNED_DIRECTIO . auto/have
fi

ngx_feature="F_NOCACHE"
ngx_feature_name="NGX_HAVE_F_NOCACHE"
ngx_feature_run=no
ngx_feature_incs="#include <fcntl.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="fcntl(0, F_NOCACHE, 1);"
. auto/feature


ngx_feature="directio()"
ngx_feature_name="NGX_HAVE_DIRECTIO"
ngx_feature_run=no
ngx_feature_incs="#include <sys/types.h>
                  #include <sys/fcntl.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="directio(0, DIRECTIO_ON);"
. auto/feature


ngx_feature="statfs()"
ngx_feature_name="NGX_HAVE_STATFS"
ngx_feature_run=no
ngx_feature_incs="$NGX_INCLUDE_SYS_PARAM_H
                  $NGX_INCLUDE_SYS_MOUNT_H
                  $NGX_INCLUDE_SYS_VFS_H"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="struct statfs  fs;
                  statfs(\".\", &fs);"
. auto/feature


ngx_feature="statvfs()"
ngx_feature_name="NGX_HAVE_STATVFS"
ngx_feature_run=no
ngx_feature_incs="#include <sys/types.h>
                  #include <sys/statvfs.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="struct statvfs  fs;
                  statvfs(\".\", &fs);"
. auto/feature


ngx_feature="dlopen()"
ngx_feature_name="NGX_HAVE_DLOPEN"
ngx_feature_run=no
ngx_feature_incs="#include <dlfcn.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="dlopen(NULL, RTLD_NOW | RTLD_GLOBAL); dlsym(NULL, NULL)"
. auto/feature


if [ $ngx_found != yes ]; then

    ngx_feature="dlopen() in libdl"
    ngx_feature_libs="-ldl"
    . auto/feature

    if [ $ngx_found = yes ]; then
        CORE_LIBS="$CORE_LIBS -ldl"
        NGX_LIBDL="-ldl"
    fi
fi


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


if [ $ngx_found != yes ]; then

    ngx_feature="sched_yield() in librt"
    ngx_feature_libs="-lrt"
    . auto/feature

    if [ $ngx_found = yes ]; then
        CORE_LIBS="$CORE_LIBS -lrt"
    fi
fi


ngx_feature="SO_SETFIB"
ngx_feature_name="NGX_HAVE_SETFIB"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="setsockopt(0, SOL_SOCKET, SO_SETFIB, NULL, 0)"
. auto/feature


ngx_feature="SO_REUSEPORT"
ngx_feature_name="NGX_HAVE_REUSEPORT"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="setsockopt(0, SOL_SOCKET, SO_REUSEPORT, NULL, 0)"
. auto/feature


ngx_feature="SO_ACCEPTFILTER"
ngx_feature_name="NGX_HAVE_DEFERRED_ACCEPT"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="setsockopt(0, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0)"
. auto/feature


# BSD way to get IPv4 datagram destination address

ngx_feature="IP_RECVDSTADDR"
ngx_feature_name="NGX_HAVE_IP_RECVDSTADDR"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>
                  #include <netinet/in.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="setsockopt(0, IPPROTO_IP, IP_RECVDSTADDR, NULL, 0)"
. auto/feature


# Linux way to get IPv4 datagram destination address

ngx_feature="IP_PKTINFO"
ngx_feature_name="NGX_HAVE_IP_PKTINFO"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>
                  #include <netinet/in.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="setsockopt(0, IPPROTO_IP, IP_PKTINFO, NULL, 0)"
. auto/feature


# RFC 3542 way to get IPv6 datagram destination address

ngx_feature="IPV6_RECVPKTINFO"
ngx_feature_name="NGX_HAVE_IPV6_RECVPKTINFO"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>
                  #include <netinet/in.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="setsockopt(0, IPPROTO_IPV6, IPV6_RECVPKTINFO, NULL, 0)"
. auto/feature


ngx_feature="TCP_DEFER_ACCEPT"
ngx_feature_name="NGX_HAVE_DEFERRED_ACCEPT"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>
                  #include <netinet/in.h>
                  #include <netinet/tcp.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_DEFER_ACCEPT, NULL, 0)"
. auto/feature


ngx_feature="TCP_KEEPIDLE"
ngx_feature_name="NGX_HAVE_KEEPALIVE_TUNABLE"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>
                  #include <netinet/in.h>
                  #include <netinet/tcp.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_KEEPIDLE, NULL, 0);
                  setsockopt(0, IPPROTO_TCP, TCP_KEEPINTVL, NULL, 0);
                  setsockopt(0, IPPROTO_TCP, TCP_KEEPCNT, NULL, 0)"
. auto/feature


ngx_feature="TCP_FASTOPEN"
ngx_feature_name="NGX_HAVE_TCP_FASTOPEN"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>
                  #include <netinet/in.h>
                  #include <netinet/tcp.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_FASTOPEN, NULL, 0)"
. auto/feature


ngx_feature="TCP_INFO"
ngx_feature_name="NGX_HAVE_TCP_INFO"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>
                  #include <netinet/in.h>
                  #include <netinet/tcp.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="socklen_t optlen = sizeof(struct tcp_info);
                  struct tcp_info ti;
                  ti.tcpi_rtt = 0;
                  ti.tcpi_rttvar = 0;
                  ti.tcpi_snd_cwnd = 0;
                  ti.tcpi_rcv_space = 0;
                  getsockopt(0, IPPROTO_TCP, TCP_INFO, &ti, &optlen)"
. auto/feature


ngx_feature="accept4()"
ngx_feature_name="NGX_HAVE_ACCEPT4"
ngx_feature_run=no
ngx_feature_incs="#include <sys/socket.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="accept4(0, NULL, NULL, SOCK_NONBLOCK)"
. auto/feature

if [ $NGX_FILE_AIO = YES ]; then

    ngx_feature="kqueue AIO support"
    ngx_feature_name="NGX_HAVE_FILE_AIO"
    ngx_feature_run=no
    ngx_feature_incs="#include <aio.h>"
    ngx_feature_path=
    ngx_feature_libs=
    ngx_feature_test="int  n; struct aiocb  iocb;
                      iocb.aio_sigevent.sigev_notify = SIGEV_KEVENT;
                      n = aio_read(&iocb)"
    . auto/feature

    if [ $ngx_found = yes ]; then
        CORE_SRCS="$CORE_SRCS $FILE_AIO_SRCS"
    fi

    if [ $ngx_found = no ]; then

        ngx_feature="Linux AIO support"
        ngx_feature_name="NGX_HAVE_FILE_AIO"
        ngx_feature_run=no
        ngx_feature_incs="#include <linux/aio_abi.h>
                          #include <sys/eventfd.h>"
        ngx_feature_path=
        ngx_feature_libs=
        ngx_feature_test="struct iocb  iocb;
                          iocb.aio_lio_opcode = IOCB_CMD_PREAD;
                          iocb.aio_flags = IOCB_FLAG_RESFD;
                          iocb.aio_resfd = -1;
                          (void) eventfd(0, 0)"
        . auto/feature

        if [ $ngx_found = yes ]; then
            have=NGX_HAVE_EVENTFD . auto/have
            have=NGX_HAVE_SYS_EVENTFD_H . auto/have
            CORE_SRCS="$CORE_SRCS $LINUX_AIO_SRCS"
        fi
    fi

    if [ $ngx_found = no ]; then

        ngx_feature="Linux AIO support (SYS_eventfd)"
        ngx_feature_incs="#include <linux/aio_abi.h>
                          #include <sys/syscall.h>"
        ngx_feature_test="int  n = SYS_eventfd;
                          struct iocb  iocb;
                          iocb.aio_lio_opcode = IOCB_CMD_PREAD;
                          iocb.aio_flags = IOCB_FLAG_RESFD;
                          iocb.aio_resfd = -1;"
        . auto/feature

        if [ $ngx_found = yes ]; then
            have=NGX_HAVE_EVENTFD . auto/have
            CORE_SRCS="$CORE_SRCS $LINUX_AIO_SRCS"
        fi
    fi

    if [ $ngx_found = no ]; then
        cat << END

$0: no supported file AIO was found
Currently file AIO is supported on FreeBSD 4.3+ and Linux 2.6.22+ only

END
        exit 1
    fi

else

    ngx_feature="eventfd()"
    ngx_feature_name="NGX_HAVE_EVENTFD"
    ngx_feature_run=no
    ngx_feature_incs="#include <sys/eventfd.h>"
    ngx_feature_path=
    ngx_feature_libs=
    ngx_feature_test="(void) eventfd(0, 0)"
    . auto/feature

    if [ $ngx_found = yes ]; then
        have=NGX_HAVE_SYS_EVENTFD_H . auto/have
    fi

    if [ $ngx_found = no ]; then

        ngx_feature="eventfd() (SYS_eventfd)"
        ngx_feature_incs="#include <sys/syscall.h>"
        ngx_feature_test="int n = SYS_eventfd"
        . auto/feature
    fi
fi


have=NGX_HAVE_UNIX_DOMAIN . auto/have

ngx_feature_libs=


# C types

ngx_type="int"; . auto/types/sizeof

ngx_type="long"; . auto/types/sizeof

ngx_type="long long"; . auto/types/sizeof

ngx_type="void *"; . auto/types/sizeof; ngx_ptr_size=$ngx_size
ngx_param=NGX_PTR_SIZE; ngx_value=$ngx_size; . auto/types/value


# POSIX types

NGX_INCLUDE_AUTO_CONFIG_H="#include \"ngx_auto_config.h\""

ngx_type="uint32_t"; ngx_types="u_int32_t"; . auto/types/typedef
ngx_type="uint64_t"; ngx_types="u_int64_t"; . auto/types/typedef

ngx_type="sig_atomic_t"; ngx_types="int"; . auto/types/typedef
. auto/types/sizeof
ngx_param=NGX_SIG_ATOMIC_T_SIZE; ngx_value=$ngx_size; . auto/types/value

ngx_type="socklen_t"; ngx_types="int"; . auto/types/typedef

ngx_type="in_addr_t"; ngx_types="uint32_t u_int32_t"; . auto/types/typedef

ngx_type="in_port_t"; ngx_types="u_short"; . auto/types/typedef

ngx_type="rlim_t"; ngx_types="int"; . auto/types/typedef

. auto/types/uintptr_t

. auto/endianness

ngx_type="size_t"; . auto/types/sizeof
ngx_param=NGX_MAX_SIZE_T_VALUE; ngx_value=$ngx_max_value; . auto/types/value
ngx_param=NGX_SIZE_T_LEN; ngx_value=$ngx_max_len; . auto/types/value

ngx_type="off_t"; . auto/types/sizeof
ngx_param=NGX_MAX_OFF_T_VALUE; ngx_value=$ngx_max_value; . auto/types/value
ngx_param=NGX_OFF_T_LEN; ngx_value=$ngx_max_len; . auto/types/value

ngx_type="time_t"; . auto/types/sizeof
ngx_param=NGX_TIME_T_SIZE; ngx_value=$ngx_size; . auto/types/value
ngx_param=NGX_TIME_T_LEN; ngx_value=$ngx_max_len; . auto/types/value
ngx_param=NGX_MAX_TIME_T_VALUE; ngx_value=$ngx_max_value; . auto/types/value


# syscalls, libc calls and some features


if [ $NGX_IPV6 = YES ]; then
    ngx_feature="AF_INET6"
    ngx_feature_name="NGX_HAVE_INET6"
    ngx_feature_run=no
    ngx_feature_incs="#include <sys/socket.h>
                      #include <netinet/in.h>
                      #include <arpa/inet.h>"
    ngx_feature_path=
    ngx_feature_libs=
    ngx_feature_test="struct sockaddr_in6  sin6;
                      sin6.sin6_family = AF_INET6;"
    . auto/feature
fi


ngx_feature="setproctitle()"
ngx_feature_name="NGX_HAVE_SETPROCTITLE"
ngx_feature_run=no
ngx_feature_incs="#include <stdlib.h>"
ngx_feature_path=
ngx_feature_libs=$NGX_SETPROCTITLE_LIB
ngx_feature_test="setproctitle(\"test\");"
. auto/feature


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);
                  if (n == -1) return 1"
. auto/feature


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);
                  if (n == -1) return 1"
. auto/feature


# pwritev() was introduced in FreeBSD 6 and Linux 2.6.30, glibc 2.10

ngx_feature="pwritev()"
ngx_feature_name="NGX_HAVE_PWRITEV"
ngx_feature_run=no
ngx_feature_incs='#include <sys/uio.h>'
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="char buf[1]; struct iovec vec[1]; ssize_t n;
                  vec[0].iov_base = buf;
                  vec[0].iov_len = 1;
                  n = pwritev(1, vec, 1, 0);
                  if (n == -1) return 1"
. auto/feature


ngx_feature="sys_nerr"
ngx_feature_name="NGX_SYS_NERR"
ngx_feature_run=value
ngx_feature_incs='#include <errno.h>
                  #include <stdio.h>'
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test='printf("%d", sys_nerr);'
. auto/feature


if [ $ngx_found = no ]; then

    # Cygiwn defines _sys_nerr
    ngx_feature="_sys_nerr"
    ngx_feature_name="NGX_SYS_NERR"
    ngx_feature_run=value
    ngx_feature_incs='#include <errno.h>
                      #include <stdio.h>'
    ngx_feature_path=
    ngx_feature_libs=
    ngx_feature_test='printf("%d", _sys_nerr);'
    . auto/feature
fi


if [ $ngx_found = no ]; then

    # Solaris has no sys_nerr
    ngx_feature='maximum errno'
    ngx_feature_name=NGX_SYS_NERR
    ngx_feature_run=value
    ngx_feature_incs='#include <errno.h>
                      #include <string.h>
                      #include <stdio.h>'
    ngx_feature_path=
    ngx_feature_libs=
    ngx_feature_test='int  n;
                      char *p;
                      for (n = 1; n < 1000; n++) {
                          errno = 0;
                          p = strerror(n);
                          if (errno == EINVAL
                              || p == NULL
                              || strncmp(p, "Unknown error", 13) == 0)
                          {
                              break;
                          }
                      }
                      printf("%d", n);'
    . auto/feature
fi


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


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);
                  if (n != 0) return 1"
. auto/feature


ngx_feature="memalign()"
ngx_feature_name="NGX_HAVE_MEMALIGN"
ngx_feature_run=no
ngx_feature_incs="#include <stdlib.h>
                  #include <malloc.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="void *p; p = memalign(4096, 4096);
                  if (p == NULL) return 1"
. auto/feature


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,
                           MAP_ANON|MAP_SHARED, -1, 0);
                  if (p == MAP_FAILED) return 1;"
. auto/feature


ngx_feature='mmap("/dev/zero", MAP_SHARED)'
ngx_feature_name="NGX_HAVE_MAP_DEVZERO"
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);
                  p = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
                  if (p == MAP_FAILED) return 1;'
. auto/feature


ngx_feature="System V shared memory"
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));
                  if (id == -1) return 1;
                  shmctl(id, IPC_RMID, NULL);"
. auto/feature


ngx_feature="POSIX semaphores"
ngx_feature_name="NGX_HAVE_POSIX_SEM"
ngx_feature_run=yes
ngx_feature_incs="#include <semaphore.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="sem_t  sem;
                  if (sem_init(&sem, 1, 0) == -1) return 1;
                  sem_destroy(&sem);"
. auto/feature


if [ $ngx_found = no ]; then

    # Linux has POSIX semaphores in libpthread
    ngx_feature="POSIX semaphores in libpthread"
    ngx_feature_libs=-lpthread
    . auto/feature

    if [ $ngx_found = yes ]; then
        CORE_LIBS="$CORE_LIBS -lpthread"
    fi
fi


if [ $ngx_found = no ]; then

    # Solaris has POSIX semaphores in librt
    ngx_feature="POSIX semaphores in librt"
    ngx_feature_libs=-lrt
    . auto/feature

    if [ $ngx_found = yes ]; then
        CORE_LIBS="$CORE_LIBS -lrt"
    fi
fi


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>
                  #include <stdio.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="struct msghdr  msg;
                  printf(\"%d\", (int) sizeof(msg.msg_control))"
. auto/feature


ngx_feature="ioctl(FIONBIO)"
ngx_feature_name="NGX_HAVE_FIONBIO"
ngx_feature_run=no
ngx_feature_incs="#include <sys/ioctl.h>
                  #include <stdio.h>
                  $NGX_INCLUDE_SYS_FILIO_H"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="int i = FIONBIO; printf(\"%d\", i)"
. auto/feature


ngx_feature="struct tm.tm_gmtoff"
ngx_feature_name="NGX_HAVE_GMTOFF"
ngx_feature_run=no
ngx_feature_incs="#include <time.h>
                  #include <stdio.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="struct tm  tm; tm.tm_gmtoff = 0;
                  printf(\"%d\", (int) tm.tm_gmtoff)"
. auto/feature


ngx_feature="struct dirent.d_namlen"
ngx_feature_name="NGX_HAVE_D_NAMLEN"
ngx_feature_run=no
ngx_feature_incs="#include <dirent.h>
                  #include <stdio.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="struct dirent  dir; dir.d_namlen = 0;
                  printf(\"%d\", (int) dir.d_namlen)"
. auto/feature


ngx_feature="struct dirent.d_type"
ngx_feature_name="NGX_HAVE_D_TYPE"
ngx_feature_run=no
ngx_feature_incs="#include <dirent.h>
                  #include <stdio.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="struct dirent  dir; dir.d_type = DT_REG;
                  printf(\"%d\", (int) dir.d_type)"
. auto/feature


ngx_feature="sysconf(_SC_NPROCESSORS_ONLN)"
ngx_feature_name="NGX_HAVE_SC_NPROCESSORS_ONLN"
ngx_feature_run=no
ngx_feature_incs=
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="sysconf(_SC_NPROCESSORS_ONLN)"
. auto/feature


ngx_feature="openat(), fstatat()"
ngx_feature_name="NGX_HAVE_OPENAT"
ngx_feature_run=no
ngx_feature_incs="#include <sys/types.h>
                  #include <sys/stat.h>
                  #include <fcntl.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="struct stat sb;
                  openat(AT_FDCWD, \".\", O_RDONLY|O_NOFOLLOW);
                  fstatat(AT_FDCWD, \".\", &sb, AT_SYMLINK_NOFOLLOW);"
. auto/feature


ngx_feature="getaddrinfo()"
ngx_feature_name="NGX_HAVE_GETADDRINFO"
ngx_feature_run=no
ngx_feature_incs="#include <sys/types.h>
                  #include <sys/socket.h>
                  #include <netdb.h>"
ngx_feature_path=
ngx_feature_libs=
ngx_feature_test='struct addrinfo *res;
                  if (getaddrinfo("localhost", NULL, NULL, &res) != 0) return 1;
                  freeaddrinfo(res)'
. auto/feature