diff options
author | Igor Sysoev <igor@sysoev.ru> | 2019-02-28 18:04:11 +0300 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2019-02-28 18:04:11 +0300 |
commit | 834e8ca576868c5ecd104bd5ebec9968c7f80a0b (patch) | |
tree | 1574f2532ffd849666e78b6a68fc7a03cfa1eb34 | |
parent | afda14d1f23cc49eee5939c25278eec3501d8631 (diff) | |
download | unit-834e8ca576868c5ecd104bd5ebec9968c7f80a0b.tar.gz unit-834e8ca576868c5ecd104bd5ebec9968c7f80a0b.tar.bz2 |
Fixed timer and event race condition.
When idle timeout occurs at the same time as a request comes in,
the timer handler closes connection while the read event triggers
request processing, and this eventually leads to segmentation fault.
-rw-r--r-- | src/nxt_conn.h | 3 | ||||
-rw-r--r-- | src/nxt_conn_read.c | 7 | ||||
-rw-r--r-- | src/nxt_conn_write.c | 5 | ||||
-rw-r--r-- | src/nxt_event_conn_job_sendfile.c | 6 | ||||
-rw-r--r-- | src/nxt_h1proto.c | 4 |
5 files changed, 17 insertions, 8 deletions
diff --git a/src/nxt_conn.h b/src/nxt_conn.h index d8b48694..7284808b 100644 --- a/src/nxt_conn.h +++ b/src/nxt_conn.h @@ -157,7 +157,8 @@ struct nxt_conn_s { nxt_sockaddr_t *local; const char *action; - uint8_t blocked; /* 1 bit */ + uint8_t block_read; /* 1 bit */ + uint8_t block_write; /* 1 bit */ uint8_t delayed; /* 1 bit */ #define NXT_CONN_SENDFILE_OFF 0 diff --git a/src/nxt_conn_read.c b/src/nxt_conn_read.c index 8228326b..83969b31 100644 --- a/src/nxt_conn_read.c +++ b/src/nxt_conn_read.c @@ -45,10 +45,11 @@ nxt_conn_io_read(nxt_task_t *task, void *obj, void *data) c = obj; - nxt_debug(task, "conn read fd:%d rdy:%d cl:%d", - c->socket.fd, c->socket.read_ready, c->socket.closed); + nxt_debug(task, "conn read fd:%d rdy:%d cl:%d er:%d bl:%d", + c->socket.fd, c->socket.read_ready, c->socket.closed, + c->socket.error, c->block_read); - if (c->socket.error != 0) { + if (c->socket.error != 0 || c->block_read) { return; } diff --git a/src/nxt_conn_write.c b/src/nxt_conn_write.c index 80d6f5cf..298d8f75 100644 --- a/src/nxt_conn_write.c +++ b/src/nxt_conn_write.c @@ -22,9 +22,10 @@ nxt_conn_io_write(nxt_task_t *task, void *obj, void *data) c = obj; - nxt_debug(task, "conn write fd:%d", c->socket.fd); + nxt_debug(task, "conn write fd:%d er:%d bl:%d", + c->socket.fd, c->socket.error, c->block_write); - if (c->socket.error != 0) { + if (c->socket.error != 0 || c->block_write) { goto error; } diff --git a/src/nxt_event_conn_job_sendfile.c b/src/nxt_event_conn_job_sendfile.c index 2ca6e421..0f6f9353 100644 --- a/src/nxt_event_conn_job_sendfile.c +++ b/src/nxt_event_conn_job_sendfile.c @@ -80,7 +80,8 @@ nxt_event_conn_job_sendfile_start(nxt_task_t *task, void *obj, void *data) c->write = NULL; jbs->ready_handler = nxt_event_conn_job_sendfile_return; - c->blocked = 1; + c->block_read = 1; + c->block_write = 1; nxt_job_start(task, &jbs->job, nxt_event_conn_job_sendfile_handler); return; @@ -170,7 +171,8 @@ nxt_event_conn_job_sendfile_return(nxt_task_t *task, void *obj, void *data) jbs = obj; c = data; - c->blocked = 0; + c->block_read = 0; + c->block_write = 0; sent = jbs->sent; c->sent += sent; diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index b5b5d6e6..07e3c7bc 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -1220,6 +1220,7 @@ nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "h1p conn request timeout"); c = nxt_read_timer_conn(timer); + c->block_read = 1; /* * Disable SO_LINGER off during socket closing * to send "408 Request Timeout" error response. @@ -1250,6 +1251,7 @@ nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "h1p conn request send timeout"); c = nxt_write_timer_conn(timer); + c->block_write = 1; h1p = c->socket.data; nxt_h1p_request_error(task, h1p, h1p->request); @@ -1464,6 +1466,7 @@ nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "h1p idle timeout"); c = nxt_read_timer_conn(timer); + c->block_read = 1; nxt_h1p_idle_response(task, c); } @@ -1559,6 +1562,7 @@ nxt_h1p_idle_response_timeout(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "h1p idle timeout response timeout"); c = nxt_read_timer_conn(timer); + c->block_write = 1; nxt_h1p_shutdown(task, c); } |