# HG changeset patch # User Igor Sysoev # Date 1066806329 0 # Node ID eac26585476ecd7302acf3cf796ff15e58bb6570 # Parent c71aeb75c07119e065fc5ea67031634d9363d549 nginx-0.0.1-2003-10-22-11:05:29 import diff --git a/src/core/ngx_hunk.c b/src/core/ngx_hunk.c --- a/src/core/ngx_hunk.c +++ b/src/core/ngx_hunk.c @@ -125,7 +125,7 @@ int ngx_chain_add_copy(ngx_pool_t *pool, void ngx_chain_update_chains(ngx_chain_t **free, ngx_chain_t **busy, - ngx_chain_t **out) + ngx_chain_t **out, ngx_hunk_tag_t tag) { ngx_chain_t *te; @@ -154,9 +154,7 @@ void ngx_chain_update_chains(ngx_chain_t } #endif - /* TODO: change to hunk->tag */ - - if (!((*busy)->hunk->type & NGX_HUNK_TEMP)) { + if ((*busy)->hunk->tag != tag) { *busy = (*busy)->next; continue; } diff --git a/src/core/ngx_hunk.h b/src/core/ngx_hunk.h --- a/src/core/ngx_hunk.h +++ b/src/core/ngx_hunk.h @@ -34,25 +34,28 @@ /* last hunk */ #define NGX_HUNK_LAST 0x2000 #define NGX_HUNK_LAST_SHADOW 0x4000 +#define NGX_HUNK_TEMP_FILE 0x8000 +typedef void * ngx_hunk_tag_t; typedef struct ngx_hunk_s ngx_hunk_t; struct ngx_hunk_s { - char *pos; - char *last; - off_t file_pos; - off_t file_last; + char *pos; + char *last; + off_t file_pos; + off_t file_last; - int type; - char *start; /* start of hunk */ - char *end; /* end of hunk */ - char *pre_start; /* start of pre-allocated hunk */ - char *post_end; /* end of post-allocated hunk */ - int tag; - ngx_file_t *file; - ngx_hunk_t *shadow; + int type; + char *start; /* start of hunk */ + char *end; /* end of hunk */ + char *pre_start; /* start of pre-allocated hunk */ + char *post_end; /* end of post-allocated hunk */ + ngx_hunk_tag_t tag; + ngx_file_t *file; + ngx_hunk_t *shadow; + /* STUB */ int num; }; @@ -119,7 +122,7 @@ ngx_hunk_t *ngx_create_temp_hunk(ngx_poo int ngx_chain_add_copy(ngx_pool_t *pool, ngx_chain_t **ch, ngx_chain_t *in); void ngx_chain_update_chains(ngx_chain_t **free, ngx_chain_t **busy, - ngx_chain_t **out); + ngx_chain_t **out, ngx_hunk_tag_t tag); 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 @@ -27,12 +27,13 @@ int ngx_event_pipe(ngx_event_pipe_t *p, } p->read = 0; + p->upstream_blocked = 0; if (ngx_event_pipe_read_upstream(p) == NGX_ABORT) { return NGX_ABORT; } - if (!p->read) { + if (!p->read && !p->upstream_blocked) { break; } @@ -140,6 +141,8 @@ int ngx_event_pipe_read_upstream(ngx_eve * a downstream is ready then write the hunks to a downstream */ + p->upstream_blocked = 1; + ngx_log_debug(p->log, "downstream ready"); break; @@ -184,6 +187,8 @@ int ngx_event_pipe_read_upstream(ngx_eve break; } + ngx_log_debug(p->log, "HUNK_FREE: %d" _ chain->hunk->num); + n = ngx_recv_chain(p->upstream, chain); ngx_log_debug(p->log, "recv_chain: %d" _ n); @@ -218,6 +223,8 @@ int ngx_event_pipe_read_upstream(ngx_eve if (n >= size) { ce->hunk->last = ce->hunk->end; + /* STUB */ ce->hunk->num = p->num++; + if (p->input_filter(p, ce->hunk) == NGX_ERROR) { return NGX_ABORT; } @@ -235,6 +242,7 @@ int ngx_event_pipe_read_upstream(ngx_eve } if ((p->upstream_eof || p->upstream_error) && p->free_raw_hunks) { + /* STUB */ p->free_raw_hunks->hunk->num = p->num++; if (p->input_filter(p, p->free_raw_hunks->hunk) == NGX_ERROR) { return NGX_ABORT; } @@ -302,6 +310,8 @@ int ngx_event_pipe_write_to_downstream(n p->out = p->out->next; ngx_remove_shadow_free_raw_hunk(&p->free_raw_hunks, ce->hunk); +ngx_log_debug(p->log, "HUNK OUT: %d %x" _ ce->hunk->num _ ce->hunk->type); + } else if (!p->cachable && p->in) { ce = p->in; @@ -313,6 +323,8 @@ int ngx_event_pipe_write_to_downstream(n p->in = p->in->next; +ngx_log_debug(p->log, "HUNK IN: %d" _ ce->hunk->num); + } else { break; } @@ -323,22 +335,32 @@ int ngx_event_pipe_write_to_downstream(n } if (out == NULL) { - break; + ngx_log_debug(p->log, "no hunks to write BUSY: %d" _ busy_len); + + if (!p->upstream_blocked || busy_len == 0) { + break; + } + + /* if the upstream is blocked then write the busy hunks */ } if (p->output_filter(p->output_ctx, out) == NGX_ERROR) { p->downstream_error = 1; + + /* handle the downstream error at the begin of the cycle. */ + continue; } - ngx_chain_update_chains(&p->free, &p->busy, &out); - - /* add the free shadow raw hunks to p->free_raw_hunks */ + ngx_chain_update_chains(&p->free, &p->busy, &out, p->tag); for (ce = p->free; ce; ce = ce->next) { + + /* add the free shadow raw hunk to p->free_raw_hunks */ + if (ce->hunk->type & NGX_HUNK_LAST_SHADOW) { h = ce->hunk->shadow; - /* THINK NEEDED ??? */ h->pos = h->last = h->start; + h->pos = h->last = h->start; h->shadow = NULL; ngx_alloc_ce_and_set_hunk(te, h, p->pool, NGX_ABORT); ngx_add_after_partially_filled_hunk(&p->free_raw_hunks, te); @@ -346,6 +368,15 @@ int ngx_event_pipe_write_to_downstream(n ce->hunk->type &= ~NGX_HUNK_LAST_SHADOW; } ce->hunk->shadow = NULL; + + if (p->cyclic_temp_file && (ce->hunk->type & NGX_HUNK_TEMP_FILE)) { + + /* reset p->temp_offset if all hunks had been sent */ + + if (ce->hunk->file_last == p->temp_offset) { + p->temp_offset = 0; + } + } } } @@ -355,7 +386,7 @@ int ngx_event_pipe_write_to_downstream(n static int ngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p) { - int rc, size, hunk_size; + int rc, size, hsize; ngx_hunk_t *h; ngx_chain_t *ce, *te, *next, *out, **le, **last_free; @@ -389,17 +420,17 @@ static int ngx_event_pipe_write_chain_to ngx_log_debug(p->log, "offset: %d" _ p->temp_offset); do { - hunk_size = ce->hunk->last - ce->hunk->pos; + hsize = ce->hunk->last - ce->hunk->pos; -ngx_log_debug(p->log, "hunk size: %d" _ hunk_size); +ngx_log_debug(p->log, "hunk size: %d" _ hsize); - if ((size + hunk_size > p->temp_file_write_size) - || (p->temp_offset + hunk_size > p->max_temp_file_size)) + if ((size + hsize > p->temp_file_write_size) + || (p->temp_offset + size + hsize > p->max_temp_file_size)) { break; } - size += hunk_size; + size += hsize; le = &ce->next; ce = ce->next; @@ -438,12 +469,17 @@ ngx_log_debug(p->log, "size: %d" _ size) ce->next = NULL; h = ce->hunk; - h->type |= NGX_HUNK_FILE; h->file = p->temp_file; h->file_pos = p->temp_offset; p->temp_offset += h->last - h->pos; h->file_last = p->temp_offset; + if (p->cachable) { + h->type |= NGX_HUNK_FILE; + } else { + h->type |= NGX_HUNK_FILE|NGX_HUNK_TEMP_FILE; + } + ngx_chain_add_ce(p->out, p->last_out, ce); if (h->type & NGX_HUNK_LAST_SHADOW) { @@ -479,10 +515,12 @@ int ngx_event_pipe_copy_input_filter(ngx ngx_memcpy(h, hunk, sizeof(ngx_hunk_t)); h->shadow = hunk; + h->tag = p->tag; h->type |= NGX_HUNK_LAST_SHADOW|NGX_HUNK_RECYCLED; hunk->shadow = h; ngx_alloc_ce_and_set_hunk(ce, h, p->pool, NGX_ERROR); +ngx_log_debug(p->log, "HUNK %d" _ h->num); ngx_chain_add_ce(p->in, p->last_in, ce); return NGX_OK; diff --git a/src/event/ngx_event_pipe.h b/src/event/ngx_event_pipe.h --- a/src/event/ngx_event_pipe.h +++ b/src/event/ngx_event_pipe.h @@ -39,13 +39,16 @@ struct ngx_event_pipe_s { unsigned read:1; unsigned cachable:1; unsigned upstream_done:1; + unsigned upstream_error:1; unsigned upstream_eof:1; - unsigned upstream_error:1; + unsigned upstream_blocked:1; unsigned downstream_done:1; unsigned downstream_error:1; + unsigned cyclic_temp_file:1; int hunks; ngx_bufs_t bufs; + ngx_hunk_tag_t tag; size_t max_busy_len; @@ -65,6 +68,7 @@ struct ngx_event_pipe_s { ngx_file_t *temp_file; ngx_path_t *temp_path; char *temp_file_warn; + /* STUB */ int num; }; diff --git a/src/http/modules/ngx_http_gzip_filter.c b/src/http/modules/ngx_http_gzip_filter.c --- a/src/http/modules/ngx_http_gzip_filter.c +++ b/src/http/modules/ngx_http_gzip_filter.c @@ -287,6 +287,8 @@ static int ngx_http_gzip_body_filter(ngx ngx_create_temp_hunk(r->pool, conf->bufs.size, 0, 0), ngx_http_gzip_error(ctx)); + ctx->out_hunk->tag = (ngx_hunk_tag_t) + &ngx_http_gzip_filter_module; ctx->out_hunk->type |= NGX_HUNK_RECYCLED; ctx->hunks++; @@ -417,7 +419,8 @@ ngx_log_debug(r->connection->log, "DEFLA return ngx_http_gzip_error(ctx); } - ngx_chain_update_chains(&ctx->free, &ctx->busy, &ctx->out); + ngx_chain_update_chains(&ctx->free, &ctx->busy, &ctx->out, + (ngx_hunk_tag_t) &ngx_http_gzip_filter_module); ctx->last_out = &ctx->out; } } 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 @@ -410,6 +410,7 @@ static void ngx_http_proxy_process_upstr ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } + p->header_in->tag = (ngx_hunk_tag_t) &ngx_http_proxy_module; } n = ngx_http_proxy_read_upstream_header(p); @@ -712,6 +713,7 @@ static void ngx_http_proxy_send_response ep->output_filter = (ngx_event_pipe_output_filter_pt) ngx_http_output_filter; ep->output_ctx = r; + ep->tag = (ngx_hunk_tag_t) &ngx_http_proxy_module; ep->bufs = p->lcf->bufs; ep->max_busy_len = p->lcf->max_busy_len; ep->upstream = p->upstream.connection; @@ -720,7 +722,7 @@ static void ngx_http_proxy_send_response ep->log = r->connection->log; ep->temp_path = p->lcf->temp_path; - ep->temp_file = ngx_palloc(r->pool, sizeof(ngx_file_t)); + ep->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)); if (ep->temp_file == NULL) { ngx_http_proxy_finalize_request(p, 0); return; @@ -750,10 +752,23 @@ static void ngx_http_proxy_send_response */ p->header_in->last = p->header_in->pos; - /* STUB */ ep->cachable = 1; -#if 0 - ep->max_temp_file_size = 1000000000; -#endif + /* STUB */ ep->cachable = 0; + + if (p->lcf->cyclic_temp_file) { + + /* + * we need to disable the use of sendfile() if we use cyclic temp file + * because the writing a new data can interfere with sendfile + * that uses the same kernel file pages + */ + + ep->cyclic_temp_file = 1; + r->sendfile = 0; + + } else { + ep->cyclic_temp_file = 0; + r->sendfile = 1; + } p->event_pipe = ep; @@ -1162,16 +1177,17 @@ static void *ngx_http_proxy_create_loc_c conf->header_size = 4096; conf->read_timeout = 30000; - conf->bufs.num = 10; + conf->bufs.num = 5; conf->bufs.size = 4096; conf->max_busy_len = 8192; /* CHECK in _init conf->max_temp_size >= conf->bufs.size !!! */ - conf->max_temp_file_size = 4096 * 6; + conf->max_temp_file_size = 4096 * 3; - conf->temp_file_write_size = 4096 * 1; + conf->temp_file_write_size = 4096 * 2; + conf->cyclic_temp_file= 1; ngx_test_null(conf->temp_path, ngx_pcalloc(cf->pool, sizeof(ngx_path_t)), NULL); 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 @@ -26,10 +26,11 @@ typedef struct { ngx_bufs_t bufs; - /* STUB */ + /* STUB names */ int max_busy_len; int max_temp_file_size; int temp_file_write_size; + int cyclic_temp_file; /* */ ngx_path_t *temp_path; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -130,6 +130,13 @@ static ngx_command_t ngx_http_core_comm offsetof(ngx_http_core_loc_conf_t, doc_root), NULL}, + {ngx_string("sendfile"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, sendfile), + NULL}, + {ngx_string("send_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_msec_slot, @@ -334,7 +341,6 @@ int ngx_http_find_location_config(ngx_ht int i, rc; ngx_http_core_loc_conf_t *clcf, **clcfp; ngx_http_core_srv_conf_t *cscf; - ngx_http_write_filter_conf_t *wcf; cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); @@ -364,14 +370,15 @@ ngx_log_debug(r->connection->log, "rc: % } } - wcf = ngx_http_get_module_loc_conf(r, ngx_http_write_filter_module); + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - if (!(ngx_io.flags & NGX_IO_SENDFILE) || !wcf->sendfile) { - r->filter = NGX_HTTP_FILTER_NEED_IN_MEMORY; + if (!(ngx_io.flags & NGX_IO_SENDFILE) || !clcf->sendfile) { + r->sendfile = 0; + + } else { + r->sendfile = 1; } - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - if (clcf->handler) { /* * if the location already has content handler then skip @@ -828,6 +835,7 @@ static void *ngx_http_core_create_loc_co */ + lcf->sendfile = NGX_CONF_UNSET; lcf->send_timeout = NGX_CONF_UNSET; lcf->discarded_buffer_size = NGX_CONF_UNSET; lcf->keepalive_timeout = NGX_CONF_UNSET; @@ -896,6 +904,7 @@ static char *ngx_http_core_merge_loc_con ngx_conf_merge_str_value(conf->default_type, prev->default_type, "text/plain"); + ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0); ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 10000); ngx_conf_merge_size_value(conf->discarded_buffer_size, prev->discarded_buffer_size, 1500); diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -110,6 +110,7 @@ typedef struct { ngx_array_t *types; ngx_str_t default_type; + int sendfile; /* sendfile */ ngx_msec_t send_timeout; /* send_timeout */ ssize_t send_lowat; /* send_lowat */ ssize_t discarded_buffer_size; /* discarded_buffer_size */ diff --git a/src/http/ngx_http_filter.h b/src/http/ngx_http_filter.h --- a/src/http/ngx_http_filter.h +++ b/src/http/ngx_http_filter.h @@ -7,12 +7,6 @@ #define NGX_HTTP_FILTER_NEED_TEMP 4 -typedef struct { - ssize_t buffer_output; - int sendfile; -} ngx_http_write_filter_conf_t; - - int ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in); int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in); @@ -20,7 +14,5 @@ int ngx_http_write_filter(ngx_http_reque extern int (*ngx_http_top_header_filter) (ngx_http_request_t *r); extern int (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch); -extern ngx_module_t ngx_http_write_filter_module; - #endif /* _NGX_HTTP_FILTER_H_INCLUDED_ */ diff --git a/src/http/ngx_http_output_filter.c b/src/http/ngx_http_output_filter.c --- a/src/http/ngx_http_output_filter.c +++ b/src/http/ngx_http_output_filter.c @@ -32,7 +32,8 @@ typedef struct { } ngx_http_output_filter_ctx_t; -static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src); +static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src, + int sendfile); static void *ngx_http_output_filter_create_conf(ngx_conf_t *cf); static char *ngx_http_output_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child); @@ -77,7 +78,8 @@ ngx_module_t ngx_http_output_filter_mod #define need_to_copy(r, hunk) \ (!ngx_hunk_special(hunk) \ - && (((r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY) \ + && (!r->sendfile \ + || ((r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY) \ && (hunk->type & NGX_HUNK_IN_MEMORY) == 0) \ || ((r->filter & NGX_HTTP_FILTER_NEED_TEMP) \ && (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP))))) @@ -162,6 +164,8 @@ int ngx_http_output_filter(ngx_http_requ ngx_create_temp_hunk(r->pool, conf->bufs.size, 0, 0), NGX_ERROR); + ctx->hunk->tag = (ngx_hunk_tag_t) + &ngx_http_output_filter_module; ctx->hunk->type |= NGX_HUNK_RECYCLED; ctx->hunks++; @@ -170,7 +174,8 @@ int ngx_http_output_filter(ngx_http_requ } } - rc = ngx_http_output_filter_copy_hunk(ctx->hunk, ctx->in->hunk); + rc = ngx_http_output_filter_copy_hunk(ctx->hunk, ctx->in->hunk, + r->sendfile); if (rc == NGX_ERROR) { return rc; @@ -215,13 +220,15 @@ int ngx_http_output_filter(ngx_http_requ last = ngx_next_filter(r, ctx->out); - ngx_chain_update_chains(&ctx->free, &ctx->busy, &ctx->out); + ngx_chain_update_chains(&ctx->free, &ctx->busy, &ctx->out, + (ngx_hunk_tag_t) &ngx_http_output_filter_module); ctx->last_out = &ctx->out; } } -static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src) +static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src, + int sendfile) { ssize_t n, size; @@ -279,6 +286,10 @@ ngx_log_debug(src->file->log, "READ: %qd src->file_pos += n; dst->last += n; + if (!sendfile) { + dst->type &= ~NGX_HUNK_FILE; + } + if ((src->type & NGX_HUNK_LAST) && src->file_pos == src->file_last) { dst->type |= NGX_HUNK_LAST; } 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 @@ -190,6 +190,9 @@ struct ngx_http_request_s { #endif unsigned pipeline:1; + /* can we use sendfile ? */ + unsigned sendfile:1; + unsigned chunked:1; unsigned header_only:1; unsigned keepalive:1; diff --git a/src/http/ngx_http_write_filter.c b/src/http/ngx_http_write_filter.c --- a/src/http/ngx_http_write_filter.c +++ b/src/http/ngx_http_write_filter.c @@ -6,6 +6,11 @@ typedef struct { + ssize_t buffer_output; +} ngx_http_write_filter_conf_t; + + +typedef struct { ngx_chain_t *out; } ngx_http_write_filter_ctx_t; @@ -18,13 +23,6 @@ static int ngx_http_write_filter_init(ng static ngx_command_t ngx_http_write_filter_commands[] = { - {ngx_string("sendfile"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_write_filter_conf_t, sendfile), - NULL}, - {ngx_string("buffer_output"), NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_size_slot, @@ -94,9 +92,6 @@ int ngx_http_write_filter(ngx_http_reque } } - conf = ngx_http_get_module_loc_conf(r->main ? r->main : r, - ngx_http_write_filter_module); - /* add the new chain to the existent one */ for (/* void */; in; in = in->next) { @@ -107,10 +102,6 @@ int ngx_http_write_filter(ngx_http_reque *le = ce; le = &ce->next; - if (!(ngx_io.flags & NGX_IO_SENDFILE) || !conf->sendfile) { - ce->hunk->type &= ~NGX_HUNK_FILE; - } - size += ngx_hunk_size(ce->hunk); if (ce->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) { @@ -128,6 +119,9 @@ int ngx_http_write_filter(ngx_http_reque last _ flush _ size); #endif + conf = ngx_http_get_module_loc_conf(r->main ? r->main : r, + ngx_http_write_filter_module); + /* * avoid the output if there is no last hunk, no flush point and * size of the hunks is smaller then "buffer_output" @@ -174,7 +168,6 @@ static void *ngx_http_write_filter_creat NULL); conf->buffer_output = NGX_CONF_UNSET; - conf->sendfile = NGX_CONF_UNSET; return conf; } @@ -187,7 +180,6 @@ static char *ngx_http_write_filter_merge ngx_http_write_filter_conf_t *conf = child; ngx_conf_merge_size_value(conf->buffer_output, prev->buffer_output, 1460); - ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0); return NULL; } diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c --- a/src/os/unix/ngx_files.c +++ b/src/os/unix/ngx_files.c @@ -77,15 +77,15 @@ ssize_t ngx_write_chain_to_file(ngx_file ce = ce->next; } - if (lseek(file->fd, offset, SEEK_SET) == -1) { - ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed"); - return NGX_ERROR; + if (file->offset != offset) { + if (lseek(file->fd, offset, SEEK_SET) == -1) { + ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed"); + return NGX_ERROR; + } } n = writev(file->fd, (struct iovec *) io.elts, io.nelts); - ngx_destroy_array(&io); - if (n == -1) { ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "writev() failed"); return NGX_ERROR; diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c --- a/src/os/unix/ngx_freebsd_sendfile_chain.c +++ b/src/os/unix/ngx_freebsd_sendfile_chain.c @@ -83,9 +83,9 @@ ngx_chain_t *ngx_freebsd_sendfile_chain( if (ce && (ce->hunk->type & NGX_HUNK_FILE)) { file = ce->hunk; - ce = ce->next; fsize = (size_t) (file->file_last - file->file_pos); fprev = file->file_last; + ce = ce->next; /* coalesce the neighbouring file hunks */