Fixing racing condition on app port release/request.

Application free ports is a queue (double linked list) protected with mutex.
After successfull request parsing, each router thread (1) tries to get port
from this list. If this list is empty, (2) start worker request posted to main
router thread. Another thread may release port between (1) and (2).

This fix adds an attempt to get port from free ports list at the beginning of
start worker action in main thread.
This commit is contained in:
Max Romanov
2017-09-05 15:56:35 -07:00
parent c937b8434a
commit 0f9f0ca522

View File

@@ -2146,13 +2146,33 @@ nxt_router_send_sw_request(nxt_task_t *task, void *obj, void *data)
uint32_t stream; uint32_t stream;
nxt_buf_t *b; nxt_buf_t *b;
nxt_app_t *app; nxt_app_t *app;
nxt_port_t *main_port, *router_port; nxt_port_t *main_port, *router_port, *app_port;
nxt_runtime_t *rt; nxt_runtime_t *rt;
nxt_start_worker_t *sw; nxt_start_worker_t *sw;
nxt_req_app_link_t *ra;
sw = obj; sw = obj;
app = sw->app; app = sw->app;
if (nxt_queue_is_empty(&app->requests)) {
ra = sw->ra;
app_port = nxt_router_app_get_port(app, ra->req_id);
if (app_port != NULL) {
nxt_debug(task, "app '%V' %p process request #%uxD",
&app->name, app, ra->req_id);
ra->app_port = app_port;
nxt_router_process_http_request_mp(task, ra, app_port);
nxt_router_ra_release(task, ra, ra->work.data);
nxt_router_sw_release(task, sw);
return;
}
}
nxt_queue_insert_tail(&app->requests, &sw->ra->link); nxt_queue_insert_tail(&app->requests, &sw->ra->link);
if (app->workers + app->pending_workers >= app->max_workers) { if (app->workers + app->pending_workers >= app->max_workers) {