summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Fedoryshchenko <denys.f@collabora.com>2026-07-06 12:43:08 +0300
committerDenys Fedoryshchenko <denys.f@collabora.com>2026-07-06 12:45:36 +0300
commit1a9923a07c1283b30a5b02a1668f57015f26232e (patch)
tree1d503fc2c5028a772b294b18fe02139521d4e9c1
parent8a94a47e8068dbc8b308cea0b875c516d2ad13f5 (diff)
downloadaccel-ppp-1a9923a07c1283b30a5b02a1668f57015f26232e.tar.gz
accel-ppp-1a9923a07c1283b30a5b02a1668f57015f26232e.zip
radius: fix request slot leak when queued request wakeup fails
req_wakeup() ignored the return value of req->send(req, 1). When a request dequeued from the req-limit queue failed at socket setup (__rad_req_send returns -2, e.g. under ephemeral port exhaustion or a routing error), the server's req_cnt slot taken in rad_server_req_exit() was never released and the request was orphaned with no callback and no timer. Leaked slots accumulate until req_cnt permanently saturates req-limit, after which every request queues forever and the server is effectively dead until restart. Handle -2 the same way rad_server_req_enter() does: release the slot, mark the server failed and drive the request through the regular failover path so it either retries on another server or reports the failure to its owner. Signed-off-by: Denys Fedoryshchenko <denys.f@collabora.com>
-rw-r--r--accel-pppd/radius/serv.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/accel-pppd/radius/serv.c b/accel-pppd/radius/serv.c
index b48e53ac..71398c82 100644
--- a/accel-pppd/radius/serv.c
+++ b/accel-pppd/radius/serv.c
@@ -152,7 +152,20 @@ static void req_wakeup(struct rad_req_t *req)
}
pthread_mutex_unlock(&req->serv->lock);
- req->send(req, 1);
+ if (req->send(req, 1) == -2) {
+ /* socket setup failed: release the slot taken in
+ * rad_server_req_exit() and drive the failover path,
+ * otherwise the server's req_cnt leaks and the request
+ * is orphaned */
+ req->active = 0;
+ pthread_mutex_lock(&req->serv->lock);
+ req->serv->req_cnt--;
+ pthread_mutex_unlock(&req->serv->lock);
+
+ rad_server_fail(req->serv);
+
+ req->send(req, -1);
+ }
}
static void req_wakeup_failed(struct rad_req_t *req)