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
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2003-10-28 18:45:41 +0300
committerIgor Sysoev <igor@sysoev.ru>2003-10-28 18:45:41 +0300
commitab0c4f5038cec58e23a023d8a1e01be038504e3e (patch)
tree2857bfcbd81676e018df566a94004ea3d942764e
parent2b0c76cfbdfd660242f47ce66a4d54d30f9b23e8 (diff)
nginx-0.0.1-2003-10-28-18:45:41 import
-rw-r--r--src/core/ngx_alloc.h2
-rw-r--r--src/event/modules/ngx_kqueue_module.c4
-rw-r--r--src/event/ngx_event.h192
-rw-r--r--src/event/ngx_event_pipe.c32
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_handler.c70
-rw-r--r--src/http/modules/proxy/ngx_http_proxy_handler.h2
-rw-r--r--src/http/ngx_http_core_module.c4
-rw-r--r--src/os/unix/ngx_freebsd_sendfile_chain.c11
-rw-r--r--src/os/unix/ngx_readv_chain.c25
-rw-r--r--src/os/unix/ngx_recv.c33
10 files changed, 191 insertions, 184 deletions
diff --git a/src/core/ngx_alloc.h b/src/core/ngx_alloc.h
index 26a8cdcdb..946361182 100644
--- a/src/core/ngx_alloc.h
+++ b/src/core/ngx_alloc.h
@@ -17,8 +17,6 @@
#define ngx_test_null(p, alloc, rc) if ((p = alloc) == NULL) { return rc; }
-#define ngx_is_null(p, alloc) if ((p = alloc) == NULL)
-
typedef struct ngx_pool_large_s ngx_pool_large_t;
diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c
index 2c743fcfb..61c724f27 100644
--- a/src/event/modules/ngx_kqueue_module.c
+++ b/src/event/modules/ngx_kqueue_module.c
@@ -422,8 +422,8 @@ static int ngx_kqueue_process_events(ngx_log_t *log)
ev->available = event_list[i].data;
if (event_list[i].flags & EV_EOF) {
- ev->eof = 1;
- ev->error = event_list[i].fflags;
+ ev->kq_eof = 1;
+ ev->kq_errno = event_list[i].fflags;
}
if (ev->oneshot && ev->timer_set) {
diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h
index 643ea2b76..f07020725 100644
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -29,8 +29,9 @@ struct ngx_event_s {
unsigned int index;
- ngx_event_t *prev; /* queue in mutex(), aio_read(), aio_write() */
- ngx_event_t *next; /* */
+ /* queue in mutex(), aio_read(), aio_write() */
+ ngx_event_t *prev;
+ ngx_event_t *next;
ngx_event_t *timer_prev;
ngx_event_t *timer_next;
@@ -40,22 +41,22 @@ struct ngx_event_s {
ngx_log_t *log;
- int available; /* kqueue only: */
- /* accept: number of sockets that wait */
- /* to be accepted */
- /* read: bytes to read */
- /* write: available space in buffer */
- /* otherwise: */
- /* accept: 1 if accept many, 0 otherwise */
+ /*
+ * kqueue only:
+ * accept: number of sockets that wait to be accepted
+ * read: bytes to read
+ * write: available space in buffer
+ *
+ * otherwise:
+ * accept: 1 if accept many, 0 otherwise
+ */
+ int available;
unsigned oneshot:1;
-#if 0
- unsigned listening:1;
-#endif
unsigned write:1;
- /* used to detect stale events in kqueue, rt signals and epoll */
+ /* used to detect the stale events in kqueue, rt signals and epoll */
unsigned instance:1;
/*
@@ -67,12 +68,12 @@ struct ngx_event_s {
/* ready event; the complete aio operation */
unsigned ready:1;
+ unsigned eof:1;
+ unsigned error:1;
+
unsigned timedout:1;
unsigned timer_set:1;
-#if 1
- unsigned blocked:1;
-#endif
unsigned delayed:1;
unsigned read_discarded:1;
@@ -87,8 +88,8 @@ struct ngx_event_s {
#endif
#if (HAVE_KQUEUE)
- unsigned eof:1;
- int error;
+ unsigned kq_eof:1;
+ int kq_errno;
#endif
#if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */
@@ -108,39 +109,25 @@ struct ngx_event_s {
#if 0
- void *thr_ctx; /* event thread context if $(CC) doesn't
- understand __thread declaration
- and pthread_getspecific() is too costly */
+
+ /* the threads support */
+
+ /*
+ * the event thread context, we store it here
+ * if $(CC) does not understand __thread declaration
+ * and pthread_getspecific() is too costly
+ */
+
+ void *thr_ctx;
#if (NGX_EVENT_T_PADDING)
- int padding[NGX_EVENT_T_PADDING]; /* event should not cross
- cache line in SMP */
-#endif
-#endif
-};
+ /* event should not cross cache line in SMP */
-#if 1
-typedef enum {
- NGX_SELECT_EVENT_N = 0,
-#if (HAVE_POLL)
- NGX_POLL_EVENT_N,
-#endif
-#if (HAVE_DEVPOLL)
- NGX_DEVPOLL_EVENT_N,
-#endif
-#if (HAVE_KQUEUE)
- NGX_KQUEUE_EVENT_N,
-#endif
-#if (HAVE_AIO)
- NGX_AIO_EVENT_N,
+ int padding[NGX_EVENT_T_PADDING];
#endif
-#if (HAVE_IOCP)
- NGX_IOCP_EVENT_N,
-#endif
- NGX_DUMMY_EVENT_N /* avoid comma at end of enumerator list */
-} ngx_event_type_e ;
#endif
+};
typedef struct {
@@ -159,6 +146,9 @@ typedef struct {
} ngx_event_actions_t;
+extern ngx_event_actions_t ngx_event_actions;
+
+
/*
* The event filter requires to read/write the whole data -
* select, poll, /dev/poll, kqueue.
@@ -243,12 +233,8 @@ typedef struct {
#define NGX_ONESHOT_EVENT EV_ONESHOT
#define NGX_CLEAR_EVENT EV_CLEAR
-#ifndef HAVE_CLEAR_EVENT
-#define HAVE_CLEAR_EVENT 1
-#endif
-
-#elif (HAVE_POLL) || (HAVE_DEVPOLL)
+#elif (HAVE_POLL)
#define NGX_READ_EVENT POLLIN
#define NGX_WRITE_EVENT POLLOUT
@@ -256,7 +242,16 @@ typedef struct {
#define NGX_LEVEL_EVENT 0
#define NGX_ONESHOT_EVENT 1
-#else
+
+#elif (HAVE_DEVPOLL)
+
+#define NGX_READ_EVENT POLLIN
+#define NGX_WRITE_EVENT POLLOUT
+
+#define NGX_LEVEL_EVENT 0
+
+
+#else /* select */
#define NGX_READ_EVENT 0
#define NGX_WRITE_EVENT 1
@@ -266,84 +261,35 @@ typedef struct {
#endif /* HAVE_KQUEUE */
-#ifndef NGX_CLEAR_EVENT
-#define NGX_CLEAR_EVENT 0 /* dummy */
+
+#if (HAVE_IOCP_EVENT)
+#define NGX_IOCP_ACCEPT 0
+#define NGX_IOCP_IO 1
#endif
-#if (USE_KQUEUE)
-#define ngx_init_events ngx_kqueue_init
-#define ngx_process_events ngx_kqueue_process_events
-#define ngx_add_event ngx_kqueue_add_event
-#define ngx_del_event ngx_kqueue_del_event
-#if 0
-#define ngx_add_timer ngx_kqueue_add_timer
-#else
-#define ngx_add_timer ngx_event_add_timer
+#ifndef NGX_CLEAR_EVENT
+#define NGX_CLEAR_EVENT 0 /* dummy declaration */
#endif
-#define ngx_event_recv ngx_event_recv_core
-#else
-#define ngx_init_events (ngx_event_init[ngx_event_type])
#define ngx_process_events ngx_event_actions.process
#define ngx_add_event ngx_event_actions.add
#define ngx_del_event ngx_event_actions.del
#define ngx_add_conn ngx_event_actions.add_conn
#define ngx_del_conn ngx_event_actions.del_conn
-#if 0
-#if (HAVE_IOCP_EVENT)
-#define ngx_event_recv ngx_event_wsarecv
-#elif (HAVE_AIO_EVENT)
-#define ngx_event_recv ngx_event_aio_read
-#else
-#define ngx_event_recv ngx_io.recv
-#define ngx_write_chain ngx_io.send_chain
-#endif
-#endif
-
-#endif
-
-
-
-
+#define ngx_add_timer ngx_event_add_timer
+#define ngx_del_timer ngx_event_del_timer
-/* ***************************** */
#define ngx_recv ngx_io.recv
#define ngx_recv_chain ngx_io.recv_chain
#define ngx_write_chain ngx_io.send_chain
-#define ngx_add_timer ngx_event_add_timer
-#define ngx_del_timer ngx_event_del_timer
-
-
-#if (HAVE_IOCP_EVENT)
-#define NGX_IOCP_ACCEPT 0
-#define NGX_IOCP_IO 1
-#endif
-
-/* ***************************** */
-
-
-
-
-
-
-#if !(USE_KQUEUE)
-extern ngx_event_actions_t ngx_event_actions;
-extern ngx_event_type_e ngx_event_type;
-extern int ngx_event_flags;
-#endif
-
-
-
-/* ***************************** */
#define NGX_EVENT_MODULE 0x544E5645 /* "EVNT" */
-
#define NGX_EVENT_CONF 0x00200000
@@ -364,8 +310,10 @@ typedef struct {
} ngx_event_module_t;
-extern ngx_module_t ngx_events_module;
-extern ngx_module_t ngx_event_core_module;
+
+extern int ngx_event_flags;
+extern ngx_module_t ngx_events_module;
+extern ngx_module_t ngx_event_core_module;
#define ngx_event_get_conf(conf_ctx, module) \
@@ -380,24 +328,10 @@ void ngx_event_acceptex(ngx_event_t *ev);
int ngx_event_post_acceptex(ngx_listening_t *ls, int n);
#endif
-/* ***************************** */
-
-
-
-
-
-ssize_t ngx_event_recv_core(ngx_connection_t *c, char *buf, size_t size);
-int ngx_event_close_connection(ngx_event_t *ev);
-
-
-int ngx_pre_thread(ngx_array_t *ls, ngx_pool_t *pool, ngx_log_t *log);
-void ngx_worker(ngx_cycle_t *cycle);
-
-
-/* ***************************** */
#include <ngx_event_timer.h>
+
#if (WIN32)
#include <ngx_iocp_module.h>
#endif
@@ -437,8 +371,9 @@ ngx_inline static int ngx_handle_read_event(ngx_event_t *rev)
return NGX_OK;
}
- if (rev->active && rev->ready) {
- if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
+ if (rev->active && (rev->ready || rev->eof)) {
+ if (ngx_del_event(rev, NGX_READ_EVENT, rev->eof ? NGX_CLOSE_EVENT : 0)
+ == NGX_ERROR) {
return NGX_ERROR;
}
@@ -551,7 +486,4 @@ ngx_inline static int ngx_handle_level_write_event(ngx_event_t *wev)
}
-/* ***************************** */
-
-
#endif /* _NGX_EVENT_H_INCLUDED_ */
diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c
index c64793d69..209f5cf23 100644
--- a/src/event/ngx_event_pipe.c
+++ b/src/event/ngx_event_pipe.c
@@ -98,20 +98,46 @@ int ngx_event_pipe_read_upstream(ngx_event_pipe_t *p)
if (ngx_event_flags == NGX_HAVE_KQUEUE_EVENT) {
- if (p->upstream->read->error) {
- ngx_log_error(NGX_LOG_ERR, p->log, p->upstream->read->error,
+ if (p->upstream->read->available == 0) {
+ if (p->upstream->read->kq_eof) {
+ p->upstream->read->ready = 0;
+ p->upstream->read->eof = 0;
+ p->upstream_eof = 1;
+ p->read = 1;
+
+ if (p->upstream->read->kq_errno) {
+ p->upstream->read->error = 1;
+ p->upstream_error = 1;
+ p->upstream_eof = 0;
+
+ ngx_log_error(NGX_LOG_ERR, p->log,
+ p->upstream->read->kq_errno,
+ /* TODO: ngx_readv_chain_n */
+ "readv() failed");
+ }
+
+ break;
+ }
+ }
+
+#if 0
+ if (p->upstream->read->kq_errno) {
+ ngx_log_error(NGX_LOG_ERR, p->log,
+ p->upstream->read->kq_errno,
"readv() failed");
p->upstream_error = 1;
break;
- } else if (p->upstream->read->eof
+ } else if (p->upstream->read->kq_eof
&& p->upstream->read->available == 0) {
p->upstream_eof = 1;
p->read = 1;
break;
}
+#endif
+
}
#endif
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c
index b4a0d425d..8483cd7ae 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -110,6 +110,13 @@ static ngx_command_t ngx_http_proxy_commands[] = {
offsetof(ngx_http_proxy_loc_conf_t, temp_file_write_size),
NULL},
+ {ngx_string("proxy_pass_server"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, pass_server),
+ NULL},
+
ngx_null_command
};
@@ -237,18 +244,10 @@ ngx_log_debug(r->connection->log, "timer_set: %d" _
ngx_del_timer(r->connection->read);
}
- ngx_is_null(cl, ngx_http_proxy_create_request(p)) {
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
-#if 0
- cl = ngx_http_proxy_create_request(p);
- if (cl == NULL) {
+ if (!(cl = ngx_http_proxy_create_request(p))) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
-#endif
if (r->request_hunks) {
cl->next = r->request_hunks;
@@ -266,6 +265,7 @@ ngx_log_debug(r->connection->log, "timer_set: %d" _
out_ctx = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t));
if (out_ctx == NULL) {
ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
}
p->output_chain_ctx = out_ctx;
@@ -288,6 +288,7 @@ ngx_log_debug(r->connection->log, "timer_set: %d" _
write_ctx = ngx_pcalloc(r->pool, sizeof(ngx_chain_write_ctx_t));
if (write_ctx == NULL) {
ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
}
out_ctx->output_ctx = write_ctx;
@@ -767,7 +768,7 @@ static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev)
return;
}
- /* NGX_AGAIN: a header line parsing is still not complete */
+ /* rc == NGX_AGAIN: a header line parsing is still not complete */
if (p->header_in->last == p->header_in->end) {
ngx_log_error(NGX_LOG_ERR, rev->log, 0,
@@ -835,6 +836,8 @@ static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p)
r = p->request;
+ r->headers_out.status = p->status;
+
r->headers_out.content_length_n = -1;
r->headers_out.content_length = NULL;
@@ -852,6 +855,16 @@ static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p)
|| &ph[i] == p->headers_in.accept_ranges) {
continue;
}
+
+ if (&ph[i] == p->headers_in.server && !p->lcf->pass_server) {
+ continue;
+ }
+ }
+
+ if (&ph[i] == p->headers_in.content_type) {
+ r->headers_out.content_type = &ph[i];
+ r->headers_out.content_type->key.len = 0;
+ continue;
}
ch = ngx_push_table(r->headers_out.headers);
@@ -862,13 +875,26 @@ static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p)
*ch = ph[i];
- if (&ph[i] == p->headers_in.content_type) {
- r->headers_out.content_type = ch;
- r->headers_out.content_type->key.len = 0;
+ /*
+ * ngx_http_header_filter() output the following headers
+ * from r->headers_out.headers if they are set:
+ * r->headers_out.server,
+ * r->headers_out.date,
+ * r->headers_out.content_length
+ */
+
+ if (&ph[i] == p->headers_in.server) {
+ r->headers_out.server = ch;
+ continue;
+ }
+
+ if (&ph[i] == p->headers_in.date) {
+ r->headers_out.date = ch;
continue;
}
if (&ph[i] == p->headers_in.content_length) {
+
r->headers_out.content_length_n =
ngx_atoi(p->headers_in.content_length->value.data,
p->headers_in.content_length->value.len);
@@ -877,23 +903,9 @@ static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p)
}
}
- /* STUB */
-
- if (p->headers_in.server) {
- r->headers_out.server = p->headers_in.server;
- }
-
- if (!p->accel && p->headers_in.date) {
- r->headers_out.date = p->headers_in.date;
- }
-
- /* */
-
/* TODO: preallocate event_pipe hunks, look "Content-Length" */
- r->headers_out.status = p->status;
-
rc = ngx_http_send_header(r);
p->header_sent = 1;
@@ -1413,6 +1425,8 @@ static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
conf->next_upstream = NGX_CONF_UNSET;
+ conf->pass_server = NGX_CONF_UNSET;
+
return conf;
}
@@ -1451,6 +1465,8 @@ static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
ngx_conf_merge_path_value(conf->temp_path, prev->temp_path,
"temp", 1, 2, 0, cf->pool);
+ ngx_conf_merge_value(conf->pass_server, prev->pass_server, 0);
+
return NULL;
}
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h
index 0f43f4f3b..f371cbc1c 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.h
@@ -32,6 +32,8 @@ typedef struct {
ssize_t temp_file_write_size;
int cyclic_temp_file;
+ int pass_server;
+
int next_upstream;
ngx_path_t *temp_path;
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 560b52696..56e99c97e 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -138,7 +138,7 @@ static ngx_command_t ngx_http_core_commands[] = {
NULL},
{ngx_string("sendfile"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_core_loc_conf_t, sendfile),
@@ -173,7 +173,7 @@ static ngx_command_t ngx_http_core_commands[] = {
NULL},
{ngx_string("msie_padding"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_core_loc_conf_t, msie_padding),
diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c
index b43562546..c24149928 100644
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -25,8 +25,8 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
{
int rc, eintr, eagain;
char *prev;
- ssize_t hsize, fsize, size;
off_t sent, fprev;
+ ssize_t hsize, fsize, size;
struct iovec *iov;
struct sf_hdtr hdtr;
ngx_err_t err;
@@ -67,15 +67,14 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
if (prev == cl->hunk->pos) {
iov->iov_len += cl->hunk->last - cl->hunk->pos;
- prev = cl->hunk->last;
} else {
ngx_test_null(iov, ngx_push_array(&header), NGX_CHAIN_ERROR);
iov->iov_base = cl->hunk->pos;
iov->iov_len = cl->hunk->last - cl->hunk->pos;
- prev = cl->hunk->last;
}
+ prev = cl->hunk->last;
hsize += cl->hunk->last - cl->hunk->pos;
}
@@ -118,14 +117,14 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
if (prev == cl->hunk->pos) {
iov->iov_len += cl->hunk->last - cl->hunk->pos;
- prev = cl->hunk->last;
} else {
ngx_test_null(iov, ngx_push_array(&trailer), NGX_CHAIN_ERROR);
iov->iov_base = cl->hunk->pos;
iov->iov_len = cl->hunk->last - cl->hunk->pos;
- prev = cl->hunk->last;
}
+
+ prev = cl->hunk->last;
}
/*
@@ -182,6 +181,7 @@ ngx_log_debug(c->log, "NOPUSH");
"sendfile() sent only %qd bytes", sent);
} else {
+ c->write->error = 1;
ngx_log_error(NGX_LOG_CRIT, c->log, err,
"sendfile() failed");
return NGX_CHAIN_ERROR;
@@ -206,6 +206,7 @@ ngx_log_debug(c->log, "NOPUSH");
ngx_log_error(NGX_LOG_INFO, c->log, err, "writev() EINTR");
} else {
+ c->write->error = 1;
ngx_log_error(NGX_LOG_CRIT, c->log, err, "writev() failed");
return NGX_CHAIN_ERROR;
}
diff --git a/src/os/unix/ngx_readv_chain.c b/src/os/unix/ngx_readv_chain.c
index c83b076ce..f19569879 100644
--- a/src/os/unix/ngx_readv_chain.c
+++ b/src/os/unix/ngx_readv_chain.c
@@ -6,23 +6,30 @@
ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
{
+ char *prev;
ssize_t n;
struct iovec *iov;
ngx_err_t err;
ngx_array_t io;
-#if (NGX_SUPPRESS_WARN)
+ prev = NULL;
iov = NULL;
-#endif
ngx_init_array(io, c->pool, 10, sizeof(struct iovec), NGX_ERROR);
- /* TODO: coalesce the neighbouring chain entries */
+ /* coalesce the neighbouring hunks */
while (chain) {
- ngx_test_null(iov, ngx_push_array(&io), NGX_ERROR);
- iov->iov_base = chain->hunk->last;
- iov->iov_len = chain->hunk->end - chain->hunk->last;
+ if (prev == chain->hunk->last) {
+ iov->iov_len += chain->hunk->end - chain->hunk->last;
+
+ } else {
+ ngx_test_null(iov, ngx_push_array(&io), NGX_ERROR);
+ iov->iov_base = chain->hunk->last;
+ iov->iov_len = chain->hunk->end - chain->hunk->last;
+ }
+
+ prev = chain->hunk->end;
chain = chain->next;
}
@@ -30,8 +37,12 @@ ngx_log_debug(c->log, "recv: %d:%d" _ io.nelts _ iov->iov_len);
n = readv(c->fd, (struct iovec *) io.elts, io.nelts);
- if (n == -1) {
+ if (n == 0) {
+ c->read->eof = 1;
+
+ } else if (n == -1) {
c->read->ready = 0;
+ c->read->error = 1;
err = ngx_errno;
if (err == NGX_EAGAIN) {
diff --git a/src/os/unix/ngx_recv.c b/src/os/unix/ngx_recv.c
index e61cc333f..1a14fd963 100644
--- a/src/os/unix/ngx_recv.c
+++ b/src/os/unix/ngx_recv.c
@@ -18,15 +18,19 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size)
if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
ngx_log_debug(c->log, "recv: eof:%d, avail:%d, err:%d" _
- rev->eof _ rev->available _ rev->error);
+ rev->kq_eof _ rev->available _ rev->kq_errno);
if (rev->available == 0) {
- if (rev->eof) {
+ if (rev->kq_eof) {
rev->ready = 0;
- if (rev->error) {
- ngx_set_socket_errno(rev->error);
- return ngx_unix_recv_error(rev, rev->error);
+ rev->eof = 1;
+
+ if (rev->kq_errno) {
+ rev->error = 1;
+ ngx_set_socket_errno(rev->kq_errno);
+ return ngx_unix_recv_error(rev, rev->kq_errno);
}
+
return 0;
} else {
@@ -43,8 +47,14 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size)
if (n >= 0) {
if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
rev->available -= n;
+
+ /*
+ * rev->available can be negative here because some additional
+ * bytes can be received between kevent() and recv()
+ */
+
if (rev->available <= 0) {
- if (!rev->eof) {
+ if (!rev->kq_eof) {
rev->ready = 0;
}
@@ -60,10 +70,15 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size)
rev->ready = 0;
}
+ if (n == 0) {
+ rev->eof = 1;
+ }
+
return n;
}
rev->ready = 0;
+ rev->error = 1;
n = ngx_unix_recv_error(rev, ngx_socket_errno);
} while (n == NGX_EINTR);
@@ -89,10 +104,16 @@ ssize_t ngx_unix_recv(ngx_connection_t *c, char *buf, size_t size)
if ((size_t) n < size) {
rev->ready = 0;
}
+
+ if (n == 0) {
+ rev->eof = 1;
+ }
+
return n;
}
rev->ready = 0;
+ rev->error = 1;
n = ngx_unix_recv_error(rev, ngx_socket_errno);
} while (n == NGX_EINTR);