diff options
author | Igor Sysoev <igor@sysoev.ru> | 2004-06-20 23:54:15 +0400 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2004-06-20 23:54:15 +0400 |
commit | 73a73b5a60b1c6c985f3e9a5d7cddbe292ad01a4 (patch) | |
tree | fe274167bb823494fe327e9f48a97a330cfe5c49 /src/os/unix | |
parent | f7290501f2426950f6c3ff7a2e3280bfaa831f0b (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.h | 16 | ||||
-rw-r--r-- | src/os/unix/ngx_freebsd_init.c | 11 | ||||
-rw-r--r-- | src/os/unix/ngx_freebsd_sendfile_chain.c | 79 | ||||
-rw-r--r-- | src/os/unix/ngx_process_cycle.c | 59 |
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)) { |