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:
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user