Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nginx/nginx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/os/unix
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2004-02-09 10:46:43 +0300
committerIgor Sysoev <igor@sysoev.ru>2004-02-09 10:46:43 +0300
commit7af6b16936b630feabecbce0dbc9cf84b4943481 (patch)
tree18301d35a84907e66fe94ddc7600d4ec6d600409 /src/os/unix
parent9260294400c902904cdf791c9c2e8fd069feec63 (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.c4
-rw-r--r--src/os/unix/ngx_freebsd_sendfile_chain.c91
-rw-r--r--src/os/unix/ngx_linux_config.h11
-rw-r--r--src/os/unix/ngx_linux_sendfile_chain.c73
-rw-r--r--src/os/unix/ngx_recv.c78
-rw-r--r--src/os/unix/ngx_recv.h12
-rw-r--r--src/os/unix/ngx_socket.c13
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)