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