diff options
author | Max Romanov <max.romanov@nginx.com> | 2017-09-05 15:56:35 -0700 |
---|---|---|
committer | Max Romanov <max.romanov@nginx.com> | 2017-09-05 15:56:35 -0700 |
commit | 0f9f0ca522fe2413d3bfb79f38c84eeaf84a17a4 (patch) | |
tree | d7c46ab179fb6e65daafc510b5a1f569736268ff | |
parent | c937b8434ab603fa0d256f9fc29229bc76683301 (diff) | |
download | unit-0f9f0ca522fe2413d3bfb79f38c84eeaf84a17a4.tar.gz unit-0f9f0ca522fe2413d3bfb79f38c84eeaf84a17a4.tar.bz2 |
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.
-rw-r--r-- | src/nxt_router.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/src/nxt_router.c b/src/nxt_router.c index f557ebaf..65ef7298 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -2146,13 +2146,33 @@ nxt_router_send_sw_request(nxt_task_t *task, void *obj, void *data) uint32_t stream; nxt_buf_t *b; 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_start_worker_t *sw; + nxt_req_app_link_t *ra; sw = obj; 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); if (app->workers + app->pending_workers >= app->max_workers) { |