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-06-20 23:54:15 +0400
committerIgor Sysoev <igor@sysoev.ru>2004-06-20 23:54:15 +0400
commit73a73b5a60b1c6c985f3e9a5d7cddbe292ad01a4 (patch)
treefe274167bb823494fe327e9f48a97a330cfe5c49 /src/os/unix
parentf7290501f2426950f6c3ff7a2e3280bfaa831f0b (diff)
nginx-0.0.7-2004-06-20-23:54:15 import
Diffstat (limited to 'src/os/unix')
-rw-r--r--src/os/unix/ngx_freebsd_config.h16
-rw-r--r--src/os/unix/ngx_freebsd_init.c11
-rw-r--r--src/os/unix/ngx_freebsd_sendfile_chain.c79
-rw-r--r--src/os/unix/ngx_process_cycle.c59
4 files changed, 115 insertions, 50 deletions
diff --git a/src/os/unix/ngx_freebsd_config.h b/src/os/unix/ngx_freebsd_config.h
index ce77ab938..570eee89b 100644
--- a/src/os/unix/ngx_freebsd_config.h
+++ b/src/os/unix/ngx_freebsd_config.h
@@ -35,6 +35,22 @@
#include <sys/sysctl.h>
#include <netinet/tcp.h> /* TCP_NOPUSH */
+
+#if __FreeBSD_version < 400017
+
+#include <sys/param.h> /* ALIGN() */
+
+/* FreeBSD 3.x has no CMSG_SPACE() at all and has the broken CMSG_DATA() */
+
+#undef CMSG_SPACE
+#define CMSG_SPACE(l) (ALIGN(sizeof(struct cmsghdr)) + ALIGN(l))
+
+#undef CMSG_DATA
+#define CMSG_DATA(cmsg) ((u_char *)(cmsg) + ALIGN(sizeof(struct cmsghdr)))
+
+#endif
+
+
#include <ngx_auto_config.h>
diff --git a/src/os/unix/ngx_freebsd_init.c b/src/os/unix/ngx_freebsd_init.c
index eb66cf067..35be16412 100644
--- a/src/os/unix/ngx_freebsd_init.c
+++ b/src/os/unix/ngx_freebsd_init.c
@@ -121,15 +121,18 @@ int ngx_os_init(ngx_log_t *log)
#if (HAVE_SENDFILE)
/*
- * The determination of the sendfile() nbytes bug is complex enough.
+ * 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.
* 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
+ * We use the algorithm that is correct at least for RELEASEs
* and for syscalls only (not libc_r wrapper).
*
- * We detect the new sendfile() version available at the compile time
+ * 4.6.1-RELEASE and below have the bug
+ * 4.6.2-RELEASE and above have the new syscall
+ *
+ * We detect the new sendfile() syscall available at the compile time
* to allow an old binary to run correctly on an updated FreeBSD system.
*/
@@ -142,7 +145,7 @@ int ngx_os_init(ngx_log_t *log)
#else
- /* an old syscall that can have the bug */
+ /* an old syscall that may have the bug */
ngx_freebsd_sendfile_nbytes_bug = 1;
diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c
index abc3d19b5..f4d8ffdeb 100644
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -11,9 +11,9 @@
/*
* 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
+ * it can not send 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
+ * may send the partially filled packets, i.e. the 8 file pages may be sent
* as the 11 full 1460-bytes packets, then one incomplete 324-bytes packet,
* and then again the 11 full 1460-bytes packets.
*
@@ -22,7 +22,7 @@
* 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.
+ * data that less than MSS so that data may be sent with 5 second delay.
* So we do not use TCP_NOPUSH on FreeBSD prior to 4.5 although it can be used
* for non-keepalive HTTP connections.
*/
@@ -32,10 +32,10 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
{
int rc;
u_char *prev;
- off_t sent, fprev;
+ off_t sent, fprev, send, limit;
size_t hsize, fsize;
ssize_t size;
- ngx_int_t eintr, eagain;
+ ngx_uint_t eintr, eagain, ready;
struct iovec *iov;
struct sf_hdtr hdtr;
ngx_err_t err;
@@ -62,12 +62,20 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
#endif
+#if 1
+ limit = 4096;
+#else
+ limit = OFF_T_MAX_VALUE;
+#endif
+
do {
file = NULL;
fsize = 0;
hsize = 0;
+ send = 0;
eintr = 0;
eagain = 0;
+ ready = 0;
ngx_init_array(header, c->pool, 10, sizeof(struct iovec),
NGX_CHAIN_ERROR);
@@ -88,40 +96,50 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
break;
}
+ size = cl->buf->last - cl->buf->pos;
+
+ if (send + size > limit) {
+ size = limit - send;
+ }
+
if (prev == cl->buf->pos) {
- iov->iov_len += cl->buf->last - cl->buf->pos;
+ iov->iov_len += size;
} else {
ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR);
iov->iov_base = (void *) cl->buf->pos;
- iov->iov_len = cl->buf->last - cl->buf->pos;
+ iov->iov_len = size;
}
- prev = cl->buf->last;
- hsize += cl->buf->last - cl->buf->pos;
+ prev = cl->buf->pos + size;
+ hsize += size;
+ send += size;
}
/* get the file buf */
if (cl && cl->buf->in_file) {
file = cl->buf;
- fsize = (size_t) (file->file_last - file->file_pos);
- fprev = file->file_last;
- cl = cl->next;
+ fsize = 0;
/* coalesce the neighbouring file bufs */
- while (cl && cl->buf->in_file) {
- if (file->file->fd != cl->buf->file->fd
- || fprev != cl->buf->file_pos)
- {
- break;
+ do {
+ size = (size_t) (cl->buf->file_last - cl->buf->file_pos);
+
+ if (send + size > limit) {
+ size = limit - send;
}
- fsize += (size_t) (cl->buf->file_last - cl->buf->file_pos);
- fprev = cl->buf->file_last;
+ fsize += size;
+ send += size;
+ fprev = cl->buf->file_pos + size;
cl = cl->next;
- }
+
+ } while (cl
+ && cl->buf->in_file
+ && file->file->fd == cl->buf->file->fd
+ && fprev == cl->buf->file_pos);
}
if (file) {
@@ -139,17 +157,24 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
break;
}
+ size = cl->buf->last - cl->buf->pos;
+
+ if (send + size > limit) {
+ size = limit - send;
+ }
+
if (prev == cl->buf->pos) {
- iov->iov_len += cl->buf->last - cl->buf->pos;
+ iov->iov_len += size;
} else {
ngx_test_null(iov, ngx_push_array(&trailer),
NGX_CHAIN_ERROR);
iov->iov_base = (void *) cl->buf->pos;
- iov->iov_len = cl->buf->last - cl->buf->pos;
+ iov->iov_len = size;
}
- prev = cl->buf->last;
+ prev = cl->buf->pos + size;
+ send += size;
}
}
@@ -261,6 +286,10 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
sent = rc > 0 ? rc : 0;
}
+ if (send == sent) {
+ ready = 1;
+ }
+
c->sent += sent;
for (cl = in; cl; cl = cl->next) {
@@ -300,6 +329,10 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
break;
}
+ if (ready) {
+ return cl;
+ }
+
in = cl;
if (eagain) {
diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c
index d1da06368..818676ae9 100644
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -763,26 +763,30 @@ int ngx_worker_thread_cycle(void *data)
ngx_int_t ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
ngx_log_t *log)
{
- ssize_t n;
- ngx_err_t err;
- struct iovec iov[1];
- struct msghdr msg;
- struct cmsghdr cm;
+ ssize_t n;
+ ngx_err_t err;
+ struct iovec iov[1];
+ struct msghdr msg;
#if (HAVE_MSGHDR_MSG_CONTROL)
+ union {
+ struct cmsghdr cm;
+ char space[CMSG_SPACE(sizeof(int))];
+ } cmsg;
+
if (ch->fd == -1) {
msg.msg_control = NULL;
msg.msg_controllen = 0;
} else {
- msg.msg_control = (caddr_t) &cm;
- msg.msg_controllen = sizeof(struct cmsghdr) + sizeof(int);
+ msg.msg_control = (caddr_t) &cmsg;
+ msg.msg_controllen = sizeof(cmsg);
- cm.cmsg_len = sizeof(struct cmsghdr) + sizeof(int);
- cm.cmsg_level = SOL_SOCKET;
- cm.cmsg_type = SCM_RIGHTS;
- *((int *) ((char *) &cm + sizeof(struct cmsghdr))) = ch->fd;
+ cmsg.cm.cmsg_len = sizeof(cmsg);
+ cmsg.cm.cmsg_level = SOL_SOCKET;
+ cmsg.cm.cmsg_type = SCM_RIGHTS;
+ *(int *) CMSG_DATA(&cmsg) = ch->fd;
}
#else
@@ -825,12 +829,19 @@ ngx_int_t ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
ngx_int_t ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
ngx_log_t *log)
{
- int fd;
- ssize_t n;
- ngx_err_t err;
- struct iovec iov[1];
- struct msghdr msg;
- struct cmsghdr cm;
+ ssize_t n;
+ ngx_err_t err;
+ struct iovec iov[1];
+ struct msghdr msg;
+
+#if (HAVE_MSGHDR_MSG_CONTROL)
+ union {
+ struct cmsghdr cm;
+ char space[CMSG_SPACE(sizeof(int))];
+ } cmsg;
+#else
+ int fd;
+#endif
iov[0].iov_base = (char *) ch;
iov[0].iov_len = size;
@@ -841,8 +852,8 @@ ngx_int_t ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
msg.msg_iovlen = 1;
#if (HAVE_MSGHDR_MSG_CONTROL)
- msg.msg_control = (caddr_t) &cm;
- msg.msg_controllen = sizeof(struct cmsghdr) + sizeof(int);
+ msg.msg_control = (caddr_t) &cmsg;
+ msg.msg_controllen = sizeof(cmsg);
#else
msg.msg_accrights = (caddr_t) &fd;
msg.msg_accrightslen = sizeof(int);
@@ -870,20 +881,22 @@ ngx_int_t ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
if (ch->command == NGX_CMD_OPEN_CHANNEL) {
- if (cm.cmsg_len < sizeof(struct cmsghdr) + sizeof(int)) {
+ if (cmsg.cm.cmsg_len < sizeof(cmsg)) {
ngx_log_error(NGX_LOG_ALERT, log, 0,
"recvmsg() returned too small ancillary data");
return NGX_ERROR;
}
- if (cm.cmsg_level != SOL_SOCKET || cm.cmsg_type != SCM_RIGHTS) {
+ if (cmsg.cm.cmsg_level != SOL_SOCKET || cmsg.cm.cmsg_type != SCM_RIGHTS)
+ {
ngx_log_error(NGX_LOG_ALERT, log, 0,
"recvmsg() returned invalid ancillary data "
- "level %d or type %d", cm.cmsg_level, cm.cmsg_type);
+ "level %d or type %d",
+ cmsg.cm.cmsg_level, cmsg.cm.cmsg_type);
return NGX_ERROR;
}
- ch->fd = *((int *) ((char *) &cm + sizeof(struct cmsghdr)));
+ ch->fd = *(int *) CMSG_DATA(&cmsg);
}
if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) {