]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] Use task_timeout instead of upstream timeout for proxy self-scan
authorVsevolod Stakhov <vsevolod@rspamd.com>
Fri, 3 Apr 2026 14:53:55 +0000 (15:53 +0100)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Fri, 3 Apr 2026 14:53:55 +0000 (15:53 +0100)
The proxy self-scan path was using default_upstream->timeout (the
milter/HTTP wire timeout, typically 120s) as the task processing
timeout. This caused tasks to linger for up to 2 minutes before
being reaped, leading to massive CLOSE_WAIT fd accumulation under
load.

Use ctx->task_timeout (derived from cfg->task_timeout, default 8s)
instead, matching how the normal worker handles task timeouts. The
previous else-if branch also had a bug where the repeat interval
used upstream timeout while the initial used cfg->task_timeout.

src/rspamd_proxy.c

index 93ef5ee8e2bc0bd6ef92e45872e0f4b3aa26d5be..e4d67c5aee26a642ac7891882f9da4b201dfc5b7 100644 (file)
@@ -2833,23 +2833,17 @@ rspamd_proxy_self_scan(struct rspamd_proxy_session *session)
                }
        }
 
-       /* Set global timeout for the task */
-       if (session->ctx->default_upstream->timeout > 0.0) {
+       /* Set global timeout for the task: use task_timeout (derived from
+        * cfg->task_timeout) rather than default_upstream->timeout, which is the
+        * milter/HTTP wire timeout and can be much larger (e.g. 120s) than the
+        * intended task processing limit. */
+       if (!isnan(session->ctx->task_timeout) && session->ctx->task_timeout > 0.0) {
                task->timeout_ev.data = task;
                ev_timer_init(&task->timeout_ev, rspamd_task_timeout,
-                                         session->ctx->default_upstream->timeout,
-                                         session->ctx->default_upstream->timeout);
+                                         session->ctx->task_timeout,
+                                         session->ctx->task_timeout);
                ev_timer_start(task->event_loop, &task->timeout_ev);
        }
-       else if (session->ctx->has_self_scan) {
-               if (!isnan(session->ctx->task_timeout) && session->ctx->task_timeout > 0) {
-                       task->timeout_ev.data = task;
-                       ev_timer_init(&task->timeout_ev, rspamd_task_timeout,
-                                                 session->ctx->cfg->task_timeout,
-                                                 session->ctx->default_upstream->timeout);
-                       ev_timer_start(task->event_loop, &task->timeout_ev);
-               }
-       }
 
        session->master_conn->task = task;
        rspamd_task_process(task, RSPAMD_TASK_PROCESS_ALL);