]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] Propagate control request ids in replies
authorVsevolod Stakhov <vsevolod@rspamd.com>
Wed, 14 Jan 2026 22:48:06 +0000 (22:48 +0000)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Wed, 14 Jan 2026 22:48:06 +0000 (22:48 +0000)
Ensure workers include cmd->id in control replies to avoid 'unknown request id 0' warnings. Update functional control tests and make RSPAMD_TMPDIR visible to child suites.

src/fuzzy_storage.c
src/hs_helper.c
src/lua/lua_worker.c
test/functional/cases/001_merged/099_control.robot [new file with mode: 0644]
test/functional/lib/rspamd.robot

index 656e13a45763c42c1ba52ad5d2692a6928dac766..70e274e1f3444cc219811fbdae276940aca7ff2c 100644 (file)
@@ -2904,8 +2904,10 @@ rspamd_fuzzy_storage_sync(struct rspamd_main *rspamd_main,
        struct rspamd_fuzzy_storage_ctx *ctx = ud;
        struct rspamd_control_reply rep;
 
-       rep.reply.fuzzy_sync.status = 0;
+       memset(&rep, 0, sizeof(rep));
        rep.type = RSPAMD_CONTROL_FUZZY_SYNC;
+       rep.id = cmd->id;
+       rep.reply.fuzzy_sync.status = 0;
 
        if (ctx->backend && worker->index == 0) {
                rspamd_fuzzy_process_updates_queue(ctx, local_db_name, FALSE);
@@ -2934,7 +2936,9 @@ rspamd_fuzzy_control_blocked(struct rspamd_main *rspamd_main,
        ev_tstamp now = ev_now(ctx->event_loop);
        rspamd_inet_addr_t *addr = NULL;
 
+       memset(&rep, 0, sizeof(rep));
        rep.type = RSPAMD_CONTROL_FUZZY_BLOCKED;
+       rep.id = cmd->id;
        rep.reply.fuzzy_blocked.status = 0;
 
        if (cmd->cmd.fuzzy_blocked.af == AF_INET) {
@@ -3017,6 +3021,7 @@ rspamd_fuzzy_storage_reload(struct rspamd_main *rspamd_main,
 
        memset(&rep, 0, sizeof(rep));
        rep.type = RSPAMD_CONTROL_RELOAD;
+       rep.id = cmd->id;
 
        if ((ctx->backend = rspamd_fuzzy_backend_create(ctx->event_loop,
                                                                                                        worker->cf->options, rspamd_main->cfg,
@@ -3458,6 +3463,7 @@ rspamd_fuzzy_storage_stat(struct rspamd_main *rspamd_main,
 
        memset(&rep, 0, sizeof(rep));
        rep.type = RSPAMD_CONTROL_FUZZY_STAT;
+       rep.id = cmd->id;
 
        rspamd_snprintf(tmppath, sizeof(tmppath), "%s%c%s-XXXXXXXXXX",
                                        rspamd_main->cfg->temp_dir, G_DIR_SEPARATOR, "fuzzy-stat");
index 90f17c9eb6350f01fa3c2c9092c8243373240d3f..36e8c36090a98146ab41521de8b26c96805ecd3e 100644 (file)
@@ -786,6 +786,7 @@ rspamd_hs_helper_reload(struct rspamd_main *rspamd_main,
        msg_info("recompiling hyperscan expressions after receiving reload command");
        memset(&rep, 0, sizeof(rep));
        rep.type = RSPAMD_CONTROL_RECOMPILE;
+       rep.id = cmd->id;
        rep.reply.recompile.status = 0;
 
        /* We write reply before actual recompilation as it takes a lot of time */
@@ -1156,6 +1157,7 @@ rspamd_hs_helper_workers_spawned(struct rspamd_main *rspamd_main,
 
        memset(&rep, 0, sizeof(rep));
        rep.type = RSPAMD_CONTROL_WORKERS_SPAWNED;
+       rep.id = cmd->id;
        rep.reply.workers_spawned.status = 0;
 
        /* Write reply */
index 7666cf1d952c95869176cfbbbbd910793383e8b1..bfe81755024080af849f2eeddc99abed735b9fa6 100644 (file)
@@ -249,6 +249,7 @@ struct rspamd_control_cbdata {
        struct ev_loop *event_loop;
        struct rspamd_async_session *session;
        enum rspamd_control_type cmd;
+       uint64_t cmd_id;
        int cbref;
        int fd;
 };
@@ -264,6 +265,7 @@ lua_worker_control_fin_session(void *ud)
 
        memset(&rep, 0, sizeof(rep));
        rep.type = cbd->cmd;
+       rep.id = cbd->cmd_id;
 
        if (write(cbd->fd, &rep, sizeof(rep)) != sizeof(rep)) {
                msg_err_pool("cannot write reply to the control socket: %s",
@@ -304,6 +306,7 @@ lua_worker_control_handler(struct rspamd_main *rspamd_main,
                                                                        cbd);
        cbd->session = session;
        cbd->fd = fd;
+       cbd->cmd_id = cmd->id;
 
        lua_pushcfunction(L, &rspamd_lua_traceback);
        err_idx = lua_gettop(L);
diff --git a/test/functional/cases/001_merged/099_control.robot b/test/functional/cases/001_merged/099_control.robot
new file mode 100644 (file)
index 0000000..6fcfc6e
--- /dev/null
@@ -0,0 +1,52 @@
+*** Settings ***
+Library         ${RSPAMD_TESTDIR}/lib/rspamd.py
+Resource        ${RSPAMD_TESTDIR}/lib/rspamd.robot
+Variables       ${RSPAMD_TESTDIR}/lib/vars.py
+
+*** Test Cases ***
+CONTROL STAT
+  [Documentation]  Test control socket stat command
+  ${result} =  Run Control Command  stat  ${RSPAMD_TMPDIR}/rspamd.sock
+  Should Be Equal As Integers  ${result.rc}  0
+  Should Contain  ${result.stdout}  workers
+  Should Contain  ${result.stdout}  total
+
+CONTROL STAT JSON
+  [Documentation]  Test control socket stat command with JSON output
+  ${result} =  Run Control Command JSON  stat  ${RSPAMD_TMPDIR}/rspamd.sock
+  Should Be Equal As Integers  ${result.rc}  0
+  Should Contain  ${result.stdout}  "workers"
+  Should Contain  ${result.stdout}  "total"
+
+CONTROL RERESOLVE
+  [Documentation]  Test control socket reresolve command
+  ${result} =  Run Control Command  reresolve  ${RSPAMD_TMPDIR}/rspamd.sock
+  Should Be Equal As Integers  ${result.rc}  0
+
+CONTROL FUZZY SYNC
+  [Documentation]  Test control socket fuzzy_sync command
+  ${result} =  Run Control Command  fuzzy_sync  ${RSPAMD_TMPDIR}/rspamd.sock
+  Should Be Equal As Integers  ${result.rc}  0
+
+CONTROL COMPOSITES STATS
+  [Documentation]  Test control socket composites_stats command
+  ${result} =  Run Control Command  composites_stats  ${RSPAMD_TMPDIR}/rspamd.sock
+  Should Be Equal As Integers  ${result.rc}  0
+  Should Contain  ${result.stdout}  checked_slow
+
+CONTROL COMPOSITES STATS JSON
+  [Documentation]  Test control socket composites_stats command with JSON output
+  ${result} =  Run Control Command JSON  composites_stats  ${RSPAMD_TMPDIR}/rspamd.sock
+  Should Be Equal As Integers  ${result.rc}  0
+  Should Contain  ${result.stdout}  checked_slow
+
+CONTROL MULTIPLE COMMANDS
+  [Documentation]  Test multiple control socket commands in sequence to verify ID matching
+  ${result1} =  Run Control Command  stat  ${RSPAMD_TMPDIR}/rspamd.sock
+  Should Be Equal As Integers  ${result1.rc}  0
+  ${result2} =  Run Control Command  reresolve  ${RSPAMD_TMPDIR}/rspamd.sock
+  Should Be Equal As Integers  ${result2.rc}  0
+  ${result3} =  Run Control Command  composites_stats  ${RSPAMD_TMPDIR}/rspamd.sock
+  Should Be Equal As Integers  ${result3.rc}  0
+  ${result4} =  Run Control Command  stat  ${RSPAMD_TMPDIR}/rspamd.sock
+  Should Be Equal As Integers  ${result4.rc}  0
index aa6a2f02cdb78eea62cb6be10cd4189e6bb8efb2..9d8b9cfad220aab4e6b72e78c5be6c9c21f6492e 100644 (file)
@@ -279,7 +279,17 @@ Rspamd Setup
   Set Directory Ownership  ${RSPAMD_TMPDIR}  ${RSPAMD_USER}  ${RSPAMD_GROUP}
 
   # Export ${RSPAMD_TMPDIR} to appropriate scope according to ${RSPAMD_SCOPE}
-  Export Scoped Variables  ${RSPAMD_SCOPE}  RSPAMD_TMPDIR=${RSPAMD_TMPDIR}
+  IF  '${RSPAMD_SCOPE}' == 'Test'
+    Set Test Variable  ${RSPAMD_TMPDIR}
+  ELSE IF  '${RSPAMD_SCOPE}' == 'Suite'
+    Set Suite Variable  ${RSPAMD_TMPDIR}
+    # Needed for child suites (e.g. directory suites with per-file .robot suites)
+    Set Global Variable  ${RSPAMD_TMPDIR}
+  ELSE IF  '${RSPAMD_SCOPE}' == 'Global'
+    Set Global Variable  ${RSPAMD_TMPDIR}
+  ELSE
+    Fail  message="Don't know what to do with scope: ${RSPAMD_SCOPE}"
+  END
 
   Run Rspamd  check_port=${check_port}
 
@@ -493,6 +503,24 @@ Sync Fuzzy Storage
   Log  ${result.stdout}
   Sleep  0.1s  Try give fuzzy storage time to sync
 
+Run Control Command
+  [Documentation]  Run a control socket command and return the result
+  [Arguments]  ${command}  ${socket}
+  ${result} =  Run Process  ${RSPAMADM}  control  -s
+  ...  ${socket}  ${command}  timeout=10s
+  Log  ${result.stdout}
+  Log  ${result.stderr}
+  [Return]  ${result}
+
+Run Control Command JSON
+  [Documentation]  Run a control socket command and return JSON result
+  [Arguments]  ${command}  ${socket}
+  ${result} =  Run Process  ${RSPAMADM}  control  -j  -s
+  ...  ${socket}  ${command}  timeout=10s
+  Log  ${result.stdout}
+  Log  ${result.stderr}
+  [Return]  ${result}
+
 Run Dummy Http
   ${result} =  Start Process  ${RSPAMD_TESTDIR}/util/dummy_http.py  -pf  /tmp/dummy_http.pid
   ...  stderr=/tmp/dummy_http.log  stdout=/tmp/dummy_http.log