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.
This commit is contained in:
@@ -157,7 +157,8 @@ struct nxt_conn_s {
|
|||||||
nxt_sockaddr_t *local;
|
nxt_sockaddr_t *local;
|
||||||
const char *action;
|
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 */
|
uint8_t delayed; /* 1 bit */
|
||||||
|
|
||||||
#define NXT_CONN_SENDFILE_OFF 0
|
#define NXT_CONN_SENDFILE_OFF 0
|
||||||
|
|||||||
@@ -45,10 +45,11 @@ nxt_conn_io_read(nxt_task_t *task, void *obj, void *data)
|
|||||||
|
|
||||||
c = obj;
|
c = obj;
|
||||||
|
|
||||||
nxt_debug(task, "conn read fd:%d rdy:%d cl:%d",
|
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.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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,9 +22,10 @@ nxt_conn_io_write(nxt_task_t *task, void *obj, void *data)
|
|||||||
|
|
||||||
c = obj;
|
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;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,8 @@ nxt_event_conn_job_sendfile_start(nxt_task_t *task, void *obj, void *data)
|
|||||||
c->write = NULL;
|
c->write = NULL;
|
||||||
jbs->ready_handler = nxt_event_conn_job_sendfile_return;
|
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);
|
nxt_job_start(task, &jbs->job, nxt_event_conn_job_sendfile_handler);
|
||||||
return;
|
return;
|
||||||
@@ -170,7 +171,8 @@ nxt_event_conn_job_sendfile_return(nxt_task_t *task, void *obj, void *data)
|
|||||||
jbs = obj;
|
jbs = obj;
|
||||||
c = data;
|
c = data;
|
||||||
|
|
||||||
c->blocked = 0;
|
c->block_read = 0;
|
||||||
|
c->block_write = 0;
|
||||||
|
|
||||||
sent = jbs->sent;
|
sent = jbs->sent;
|
||||||
c->sent += sent;
|
c->sent += sent;
|
||||||
|
|||||||
@@ -1220,6 +1220,7 @@ nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj, void *data)
|
|||||||
nxt_debug(task, "h1p conn request timeout");
|
nxt_debug(task, "h1p conn request timeout");
|
||||||
|
|
||||||
c = nxt_read_timer_conn(timer);
|
c = nxt_read_timer_conn(timer);
|
||||||
|
c->block_read = 1;
|
||||||
/*
|
/*
|
||||||
* Disable SO_LINGER off during socket closing
|
* Disable SO_LINGER off during socket closing
|
||||||
* to send "408 Request Timeout" error response.
|
* 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");
|
nxt_debug(task, "h1p conn request send timeout");
|
||||||
|
|
||||||
c = nxt_write_timer_conn(timer);
|
c = nxt_write_timer_conn(timer);
|
||||||
|
c->block_write = 1;
|
||||||
h1p = c->socket.data;
|
h1p = c->socket.data;
|
||||||
|
|
||||||
nxt_h1p_request_error(task, h1p, h1p->request);
|
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");
|
nxt_debug(task, "h1p idle timeout");
|
||||||
|
|
||||||
c = nxt_read_timer_conn(timer);
|
c = nxt_read_timer_conn(timer);
|
||||||
|
c->block_read = 1;
|
||||||
|
|
||||||
nxt_h1p_idle_response(task, c);
|
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");
|
nxt_debug(task, "h1p idle timeout response timeout");
|
||||||
|
|
||||||
c = nxt_read_timer_conn(timer);
|
c = nxt_read_timer_conn(timer);
|
||||||
|
c->block_write = 1;
|
||||||
|
|
||||||
nxt_h1p_shutdown(task, c);
|
nxt_h1p_shutdown(task, c);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user