# HG changeset patch # User Igor Sysoev # Date 1069174140 0 # Node ID c966c09be66b56b5aa4c29b269e34da19601dcb8 # Parent 0061d1f0908ddf7ac20ac7324aef42c3b0533da0 nginx-0.0.1-2003-11-18-19:49:00 import diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c --- a/src/event/modules/ngx_kqueue_module.c +++ b/src/event/modules/ngx_kqueue_module.c @@ -285,9 +285,9 @@ static int ngx_kqueue_set_event(ngx_even #if (HAVE_LOWAT_EVENT) - if ((flags & EV_ADD) && ev->lowat > 0) { + if (flags & NGX_LOWAT_EVENT) { change_list[nchanges].fflags = NOTE_LOWAT; - change_list[nchanges].data = ev->lowat; + change_list[nchanges].data = ev->available; } else { change_list[nchanges].fflags = 0; diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -45,13 +45,20 @@ struct ngx_event_s { /* * kqueue only: * accept: number of sockets that wait to be accepted - * read: bytes to read - * write: available space in buffer + * read: bytes to read when event is ready + * or lowat when event is set with NGX_LOWAT_EVENT flag + * write: available space in buffer when event is ready + * or lowat when event is set with NGX_LOWAT_EVENT flag * * otherwise: * accept: 1 if accept many, 0 otherwise */ + +#if (HAVE_KQUEUE) int available; +#else + unsigned available:1; +#endif unsigned oneshot:1; @@ -104,10 +111,6 @@ struct ngx_event_s { int kq_errno; #endif -#if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */ - int lowat; -#endif - #if (HAVE_AIO) @@ -224,7 +227,11 @@ extern ngx_event_actions_t ngx_event_a * /dev/poll: we need to flush POLLREMOVE event before closing file */ -#define NGX_CLOSE_EVENT 1 +#define NGX_CLOSE_EVENT 1 + + +/* this flag has meaning only for kqueue */ +#define NGX_LOWAT_EVENT 0 #if (HAVE_KQUEUE) @@ -233,13 +240,17 @@ extern ngx_event_actions_t ngx_event_a #define NGX_WRITE_EVENT EVFILT_WRITE /* - * NGX_CLOSE_EVENT is the module flag and it would not go into a kernel - * so we need to choose the value that would not interfere with any existent - * and future flags. kqueue has such values - EV_FLAG1, EV_EOF and EV_ERROR. - * They are reserved and cleared on a kernel entrance. + * NGX_CLOSE_EVENT and NGX_LOWAT_EVENT are the module flags and they would + * not go into a kernel so we need to choose the value that would not interfere + * with any existent and future kqueue flags. kqueue has such values - + * EV_FLAG1, EV_EOF and EV_ERROR. They are reserved and cleared on a kernel + * entrance. */ #undef NGX_CLOSE_EVENT -#define NGX_CLOSE_EVENT EV_FLAG1 +#define NGX_CLOSE_EVENT EV_EOF + +#undef NGX_LOWAT_EVENT +#define NGX_LOWAT_EVENT EV_FLAG1 #define NGX_LEVEL_EVENT 0 #define NGX_ONESHOT_EVENT EV_ONESHOT @@ -351,7 +362,7 @@ int ngx_event_post_acceptex(ngx_listenin -ngx_inline static int ngx_handle_read_event(ngx_event_t *rev, int close) +ngx_inline static int ngx_handle_read_event(ngx_event_t *rev, int flags) { if (ngx_event_flags & NGX_USE_CLEAR_EVENT) { @@ -380,10 +391,8 @@ ngx_inline static int ngx_handle_read_ev return NGX_OK; } - if (rev->active && (rev->ready || close)) { - if (ngx_del_event(rev, NGX_READ_EVENT, close ? NGX_CLOSE_EVENT : 0) - == NGX_ERROR) - { + if (rev->active && (rev->ready || (flags & NGX_CLOSE_EVENT))) { + if (ngx_del_event(rev, NGX_READ_EVENT, flags) == NGX_ERROR) { return NGX_ERROR; } @@ -423,21 +432,14 @@ ngx_inline static int ngx_handle_level_r } -ngx_inline static int ngx_handle_write_event(ngx_event_t *wev, int lowat) +ngx_inline static int ngx_handle_write_event(ngx_event_t *wev, int flags) { if (ngx_event_flags & NGX_USE_CLEAR_EVENT) { /* kqueue */ -#if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */ - - if (ngx_event_flags & NGX_HAVE_LOWAT_EVENT) { - wev->lowat = lowat; - } - -#endif if (!wev->active && !wev->ready) { - if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_CLEAR_EVENT) + if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_CLEAR_EVENT|flags) == NGX_ERROR) { return NGX_ERROR; } diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c --- a/src/event/ngx_event_connect.c +++ b/src/event/ngx_event_connect.c @@ -260,6 +260,8 @@ ngx_log_debug(pc->log, "CONNECT: %s" _ p return NGX_AGAIN; } +ngx_log_debug(pc->log, "CONNECTED"); + wev->ready = 1; return NGX_OK; diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c --- a/src/event/ngx_event_pipe.c +++ b/src/event/ngx_event_pipe.c @@ -19,6 +19,7 @@ static int ngx_event_pipe_drain_chains(n int ngx_event_pipe(ngx_event_pipe_t *p, int do_write) { + int flags; ngx_event_t *rev, *wev; for ( ;; ) { @@ -45,7 +46,9 @@ int ngx_event_pipe(ngx_event_pipe_t *p, if (p->upstream->fd != -1) { rev = p->upstream->read; - if (ngx_handle_read_event(rev, (rev->eof || rev->error)) == NGX_ERROR) { + flags = (rev->eof || rev->error) ? NGX_CLOSE_EVENT : 0; + + if (ngx_handle_read_event(rev, flags) == NGX_ERROR) { return NGX_ABORT; } @@ -54,12 +57,10 @@ int ngx_event_pipe(ngx_event_pipe_t *p, } } -ngx_log_debug(p->log, "DOWN: %d" _ p->downstream->fd); - if (p->downstream->fd != -1) { wev = p->downstream->write; - - if (ngx_handle_write_event(wev, p->send_lowat) == NGX_ERROR) { + wev->available = p->send_lowat; + if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) { return NGX_ABORT; } diff --git a/src/http/modules/proxy/ngx_http_proxy_cache.c b/src/http/modules/proxy/ngx_http_proxy_cache.c --- a/src/http/modules/proxy/ngx_http_proxy_cache.c +++ b/src/http/modules/proxy/ngx_http_proxy_cache.c @@ -283,8 +283,28 @@ void ngx_http_proxy_cache_busy_lock(ngx_ p->cache->ctx.file.info_valid = 1; } + if (rc == NGX_AGAIN) { - if (rc == NGX_AGAIN) { + if ((ngx_event_flags & (NGX_USE_CLEAR_EVENT|NGX_HAVE_KQUEUE_EVENT)) + && !p->request->connection->write->active) + { + /* + * kqueue allows to detect when client closes prematurely + * connection + */ + + p->request->connection->write->event_handler = + ngx_http_proxy_check_broken_connection; + + if (ngx_add_event(p->request->connection->write, NGX_WRITE_EVENT, + NGX_CLEAR_EVENT) == NGX_ERROR) + { + ngx_http_proxy_finalize_request(p, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + } + return; } diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c --- a/src/http/modules/proxy/ngx_http_proxy_handler.c +++ b/src/http/modules/proxy/ngx_http_proxy_handler.c @@ -338,6 +338,45 @@ static int ngx_http_proxy_handler(ngx_ht } +void ngx_http_proxy_check_broken_connection(ngx_event_t *wev) +{ + ngx_connection_t *c; + ngx_http_request_t *r; + ngx_http_proxy_ctx_t *p; + + ngx_log_debug(wev->log, "http proxy check client"); + + c = wev->data; + r = c->data; + p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); + +#if (HAVE_KQUEUE) + if (wev->kq_eof) { + wev->eof = 1; + + if (wev->kq_errno) { + wev->error = 1; + } + + if (!p->cachable && p->upstream->peer.connection) { + ngx_log_error(NGX_LOG_INFO, wev->log, wev->kq_errno, + "client closed prematurely connection, " + "so upstream connection is closed too"); + ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST); + return; + } + + ngx_log_error(NGX_LOG_INFO, wev->log, wev->kq_errno, + "client closed prematurely connection"); + + if (p->upstream == NULL || p->upstream->peer.connection == NULL) { + ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST); + } + } +#endif +} + + void ngx_http_proxy_busy_lock_handler(ngx_event_t *rev) { ngx_connection_t *c; @@ -351,6 +390,12 @@ void ngx_http_proxy_busy_lock_handler(ng p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); p->action = "waiting upstream in busy lock"; + if (p->request->connection->write->eof) { + ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock); + ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST); + return; + } + if (rev->timedout) { rev->timedout = 0; p->busy_lock.time++; @@ -369,14 +414,15 @@ void ngx_http_proxy_busy_lock_handler(ng /* * TODO: kevent() notify about error, otherwise we need to - * call ngx_peek(): recv(MGS_PEEK) to get errno. THINK about aio + * call ngx_peek(): recv(MSG_PEEK) to get errno. THINK about aio * if there's no error we need to disable event. */ +#if 0 #if (HAVE_KQUEUE) if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) && rev->kq_eof) { - p->lcf->busy_lock->waiting--; + ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock); ngx_del_timer(rev); @@ -388,13 +434,12 @@ void ngx_http_proxy_busy_lock_handler(ng return; } - /* we have not HTTP code for the case when a client cancels a request */ - - ngx_http_proxy_finalize_request(p, 0); + ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST); return; } #endif +#endif } diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h --- a/src/http/modules/proxy/ngx_http_proxy_handler.h +++ b/src/http/modules/proxy/ngx_http_proxy_handler.h @@ -203,6 +203,8 @@ int ngx_http_proxy_send_cached_response( int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p); int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p); +void ngx_http_proxy_check_broken_connection(ngx_event_t *wev); + void ngx_http_proxy_busy_lock_handler(ngx_event_t *rev); void ngx_http_proxy_cache_busy_lock(ngx_http_proxy_ctx_t *p); void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p); diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c --- a/src/http/modules/proxy/ngx_http_proxy_upstream.c +++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c @@ -19,7 +19,6 @@ static void ngx_http_proxy_process_upstr static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev); static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *); static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p); -static void ngx_http_proxy_check_broken_connection(ngx_event_t *wev); static void ngx_http_proxy_process_body(ngx_event_t *ev); static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p, int ft_type); @@ -502,8 +501,8 @@ static void ngx_http_proxy_send_request( if (rc == NGX_AGAIN) { ngx_add_timer(c->write, p->lcf->send_timeout); - if (ngx_handle_write_event(c->write, /* STUB: lowat */ 0) == NGX_ERROR) - { + c->write->available = /* STUB: lowat */ 0; + if (ngx_handle_write_event(c->write, NGX_LOWAT_EVENT) == NGX_ERROR) { ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } @@ -526,6 +525,8 @@ static void ngx_http_proxy_send_request( return; } + ngx_add_timer(c->read, p->lcf->read_timeout); + #if 0 if (c->read->ready) { @@ -566,9 +567,11 @@ static void ngx_http_proxy_send_request_ return; } - if (p->request->connection->write->eof) { - ngx_http_proxy_close_connection(p); - ngx_http_close_connection(p->request->connection); + if (p->request->connection->write->eof + && (!p->cachable || !p->request_sent)) + { + ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST); + return; } ngx_http_proxy_send_request(p); @@ -868,7 +871,9 @@ static ssize_t ngx_http_proxy_read_upstr p->header_in->end - p->header_in->last); if (n == NGX_AGAIN) { +#if 0 ngx_add_timer(rev, p->lcf->read_timeout); +#endif if (ngx_handle_read_event(rev, 0) == NGX_ERROR) { ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); @@ -1042,45 +1047,6 @@ static void ngx_http_proxy_send_response } -static void ngx_http_proxy_check_broken_connection(ngx_event_t *wev) -{ - ngx_connection_t *c; - ngx_http_request_t *r; - ngx_http_proxy_ctx_t *p; - - ngx_log_debug(wev->log, "http proxy check client"); - - c = wev->data; - r = c->data; - p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); - -#if (HAVE_KQUEUE) - if (wev->kq_eof) { - wev->eof = 1; - - if (wev->kq_errno) { - wev->error = 1; - } - - if (!p->cachable && p->upstream->peer.connection) { - ngx_log_error(NGX_LOG_INFO, wev->log, wev->kq_errno, - "client closed prematurely connection, " - "so upstream connection is closed too"); - ngx_http_proxy_close_connection(p); - - } else { - ngx_log_error(NGX_LOG_INFO, wev->log, wev->kq_errno, - "client closed prematurely connection"); - } - - if (p->upstream->peer.connection == NULL) { - ngx_http_close_connection(c); - } - } -#endif -} - - static void ngx_http_proxy_process_body(ngx_event_t *ev) { ngx_connection_t *c; @@ -1215,6 +1181,11 @@ ngx_log_debug(p->request->connection->lo ngx_http_proxy_close_connection(p); } + if (p->request->connection->write->eof) { + ngx_http_proxy_finalize_request(p, status ? status: + NGX_HTTP_CLIENT_CLOSED_REQUEST); + } + if (status) { p->state->status = status; diff --git a/src/http/ngx_http_busy_lock.c b/src/http/ngx_http_busy_lock.c --- a/src/http/ngx_http_busy_lock.c +++ b/src/http/ngx_http_busy_lock.c @@ -103,6 +103,10 @@ ngx_log_debug(bc->event->log, "BUSYLOCK: void ngx_http_busy_unlock(ngx_http_busy_lock_t *bl, ngx_http_busy_lock_ctx_t *bc) { + if (bl == NULL) { + return; + } + if (bl->md5) { bl->md5_mask[bc->slot / 8] &= ~(1 << (bc->slot & 7)); bl->cachable--; diff --git a/src/http/ngx_http_cache.c b/src/http/ngx_http_cache.c --- a/src/http/ngx_http_cache.c +++ b/src/http/ngx_http_cache.c @@ -107,6 +107,13 @@ int ngx_http_cache_open_file(ngx_http_re ctx->date = h->date; ctx->length = h->length; + if (h->key_len > (size_t) (ctx->buf->last - ctx->buf->pos)) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + "cache file \"%s\" is probably invalid", + ctx->file.name.data); + return NGX_DECLINED; + } + if (h->key_len != ctx->key.len || ngx_strncmp(h->key, ctx->key.data, h->key_len) != 0) { diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -664,6 +664,10 @@ static ssize_t ngx_http_read_request_hea return n; } + if (!rev->ready) { + return NGX_AGAIN; + } + n = ngx_recv(r->connection, r->header_in->last, r->header_in->end - r->header_in->last); @@ -853,7 +857,8 @@ static void ngx_http_set_write_handler(n ngx_http_core_module); ngx_add_timer(wev, clcf->send_timeout); - if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) { + wev->available = clcf->send_lowat; + if (ngx_handle_write_event(wev, NGX_LOWAT_EVENT) == NGX_ERROR) { ngx_http_close_request(r, 0); ngx_http_close_connection(r->connection); } diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -49,6 +49,12 @@ #define NGX_HTTP_REQUEST_URI_TOO_LARGE 414 #define NGX_HTTP_RANGE_NOT_SATISFIABLE 416 +/* + * HTTP does not define a code for the case when a client closed a connection + * while we are processing request so we introduce own code to log this case + */ +#define NGX_HTTP_CLIENT_CLOSED_REQUEST 420 + #define NGX_HTTP_INTERNAL_SERVER_ERROR 500 #define NGX_HTTP_NOT_IMPLEMENTED 501 #define NGX_HTTP_BAD_GATEWAY 502 diff --git a/src/os/unix/ngx_freebsd_config.h b/src/os/unix/ngx_freebsd_config.h --- a/src/os/unix/ngx_freebsd_config.h +++ b/src/os/unix/ngx_freebsd_config.h @@ -33,11 +33,13 @@ typedef u_int32_t uintptr_t; #endif +/* TODO: autoconf ??? */ #if __FreeBSD_version < 330002 /* exactly */ typedef uint32_t socklen_t; #endif +/* TODO: autoconf */ #if (i386) #define OFF_FMT "%lld" @@ -52,7 +54,7 @@ typedef uint32_t socklen_t; #endif -#define TIME_FMT "%lu" +#define TIME_FMT "%ld" #define PID_FMT "%d" #define RLIM_FMT "%lld" @@ -91,8 +93,8 @@ typedef uint32_t socklen_t; /* STUB */ -#define HAVE_PREAD 1 -#define HAVE_PWRITE 1 +#define HAVE_PREAD 0 +#define HAVE_PWRITE 0 #define HAVE_LOCALTIME_R 1 diff --git a/src/os/unix/ngx_linux_config.h b/src/os/unix/ngx_linux_config.h --- a/src/os/unix/ngx_linux_config.h +++ b/src/os/unix/ngx_linux_config.h @@ -34,7 +34,7 @@ #define OFF_FMT "%lld" #define SIZE_FMT "%d" #define SIZEX_FMT "%x" -#define TIME_FMT "%lu" +#define TIME_FMT "%ld" #define PID_FMT "%d" #define RLIM_FMT "%lu" diff --git a/src/os/unix/ngx_solaris_config.h b/src/os/unix/ngx_solaris_config.h --- a/src/os/unix/ngx_solaris_config.h +++ b/src/os/unix/ngx_solaris_config.h @@ -33,7 +33,7 @@ typedef uint32_t u_int32_t; #define OFF_FMT "%lld" #define SIZE_FMT "%d" #define SIZEX_FMT "%x" -#define TIME_FMT "%lu" +#define TIME_FMT "%ld" #define PID_FMT "%ld" #define RLIM_FMT "%lu"