summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_router.c
diff options
context:
space:
mode:
authorMax Romanov <max.romanov@nginx.com>2017-09-05 15:56:35 -0700
committerMax Romanov <max.romanov@nginx.com>2017-09-05 15:56:35 -0700
commit0f9f0ca522fe2413d3bfb79f38c84eeaf84a17a4 (patch)
treed7c46ab179fb6e65daafc510b5a1f569736268ff /src/nxt_router.c
parentc937b8434ab603fa0d256f9fc29229bc76683301 (diff)
downloadunit-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.
Diffstat (limited to 'src/nxt_router.c')
-rw-r--r--src/nxt_router.c22
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) {