Skip to content

Commit

Permalink
Fixed timeouts with threaded sendfile() and subrequests.
Browse files Browse the repository at this point in the history
If a write event happens after sendfile() but before we've got the
sendfile results in the main thread, this write event will be ignored.
And if no more events will happen, the connection will hang.

Removing the events works in the simple cases, but not always, as
in some cases events are added back by an unrelated code.  E.g.,
the upstream module adds write event in the ngx_http_upstream_init()
to track client aborts.

Fix is to use wev->complete instead.  It is now set to 0 before
a sendfile() task is posted, and it is set to 1 once a write event
happens.  If on completion of the sendfile() task wev->complete is 1,
we know that an event happened while we were executing sendfile(), and
the socket is still ready for writing even if sendfile() did not sent
all the data or returned EAGAIN.
  • Loading branch information
mdounin committed Mar 18, 2016
1 parent 07fc7dc commit 931ce7f
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 10 deletions.
3 changes: 3 additions & 0 deletions src/event/modules/ngx_epoll_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,9 @@ ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
}

wev->ready = 1;
#if (NGX_THREADS)
wev->complete = 1;
#endif

if (flags & NGX_POST_EVENTS) {
ngx_post_event(wev, &ngx_posted_events);
Expand Down
21 changes: 11 additions & 10 deletions src/os/unix/ngx_linux_sendfile_chain.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,6 @@ static ngx_int_t
ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, size_t size,
size_t *sent)
{
ngx_uint_t flags;
ngx_event_t *wev;
ngx_thread_task_t *task;
ngx_linux_sendfile_ctx_t *ctx;
Expand Down Expand Up @@ -358,6 +357,11 @@ ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, size_t size,

if (ctx->err == NGX_EAGAIN) {
*sent = 0;

if (wev->complete) {
return NGX_DONE;
}

return NGX_AGAIN;
}

Expand All @@ -382,7 +386,11 @@ ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, size_t size,

*sent = ctx->sent;

return (ctx->sent == ctx->size) ? NGX_DONE : NGX_AGAIN;
if (ctx->sent == ctx->size || wev->complete) {
return NGX_DONE;
}

return NGX_AGAIN;
}

if (task->event.active && ctx->file == file) {
Expand All @@ -400,14 +408,7 @@ ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, size_t size,
ctx->socket = c->fd;
ctx->size = size;

if (wev->active) {
flags = (ngx_event_flags & NGX_USE_CLEAR_EVENT) ? NGX_CLEAR_EVENT
: NGX_LEVEL_EVENT;

if (ngx_del_event(wev, NGX_WRITE_EVENT, flags) == NGX_ERROR) {
return NGX_ERROR;
}
}
wev->complete = 0;

if (file->file->thread_handler(task, file->file) != NGX_OK) {
return NGX_ERROR;
Expand Down

0 comments on commit 931ce7f

Please sign in to comment.