From: Vsevolod Stakhov Date: Thu, 23 Jul 2026 13:13:06 +0000 (+0100) Subject: [Fix] lua_http: deliver errors to coroutine callers X-Git-Tag: 4.1.3~31 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0eddd23ddf7703ca4f11ad193eacdfb6c2f63ad8;p=thirdparty%2Frspamd.git [Fix] lua_http: deliver errors to coroutine callers DNS-stage failures (resolve error, no records, connection refused) went through lua_http_push_error, which unconditionally invoked the callback reference; coroutine-style requests have no callback (cbref == -1), so the error was swallowed and the yielded thread was never resumed. Resume the thread with (err, nil) instead, mirroring the connection error path. Synchronous failures (unparseable URL, blocked session, immediate connection or DNS-send failure) returned a bare false, which coroutine callers read as err = false, response = nil - a crash on response.code for every caller checking 'if not err'. Return (err, nil) there as well. --- diff --git a/src/lua/lua_http.c b/src/lua/lua_http.c index 6c9cca0d1e..2ea48698ba 100644 --- a/src/lua/lua_http.c +++ b/src/lua/lua_http.c @@ -304,6 +304,29 @@ lua_http_push_error(struct lua_http_cbdata *cbd, const char *err) struct lua_callback_state lcbd; lua_State *L; + if (cbd->cbref == -1) { + /* Coroutine-style call: resume the yielded thread with (err, nil) */ + if (cbd->flags & RSPAMD_LUA_HTTP_FLAG_YIELDED) { + cbd->flags &= ~RSPAMD_LUA_HTTP_FLAG_YIELDED; + + L = cbd->thread->lua_state; + lua_pushstring(L, err); + lua_pushnil(L); + + if (cbd->item) { + rspamd_symcache_set_cur_item(cbd->task, cbd->item); + } + + lua_thread_resume_checked(cbd->thread, cbd->thread_generation, 2); + } + else { + msg_info("lost HTTP error for %s in coroutines mess: %s", + cbd->host ? cbd->host : "unknown host", err); + } + + return; + } + lua_thread_pool_prepare_callback(cbd->cfg->lua_thread_pool, &lcbd); L = lcbd.L; @@ -975,6 +998,14 @@ lua_http_request(lua_State *L) msg = rspamd_http_message_from_url(url); if (msg == NULL) { msg_err_task_check("cannot create HTTP message from url %s", url); + + if (cbref == -1) { + /* Coroutine callers expect (err, response), not a bare false */ + lua_pushstring(L, "cannot create HTTP message from url"); + lua_pushnil(L); + return 2; + } + lua_pushboolean(L, FALSE); return 1; } @@ -1243,8 +1274,6 @@ lua_http_request(lua_State *L) } if (session && rspamd_session_blocked(session)) { - lua_pushboolean(L, FALSE); - g_free(auth); rspamd_http_message_unref(msg); if (body) { @@ -1254,6 +1283,16 @@ lua_http_request(lua_State *L) rspamd_keypair_unref(local_kp); } + if (cbref == -1) { + /* Coroutine callers expect (err, response), not a bare false */ + lua_pushstring(L, "session is terminating"); + lua_pushnil(L); + + return 2; + } + + lua_pushboolean(L, FALSE); + return 1; } if (task == NULL && cfg == NULL) { @@ -1406,6 +1445,15 @@ lua_http_request(lua_State *L) } REF_RELEASE(cbd); + + if (cbref == -1) { + /* Coroutine callers expect (err, response), not a bare false */ + lua_pushstring(L, "cannot make HTTP connection"); + lua_pushnil(L); + + return 2; + } + lua_pushboolean(L, FALSE); return 1; @@ -1431,6 +1479,15 @@ lua_http_request(lua_State *L) } REF_RELEASE(cbd); + + if (cbref == -1) { + /* Coroutine callers expect (err, response), not a bare false */ + lua_pushstring(L, "cannot make DNS request"); + lua_pushnil(L); + + return 2; + } + lua_pushboolean(L, FALSE); return 1; @@ -1449,6 +1506,15 @@ lua_http_request(lua_State *L) } REF_RELEASE(cbd); + + if (cbref == -1) { + /* Coroutine callers expect (err, response), not a bare false */ + lua_pushstring(L, "cannot make DNS request"); + lua_pushnil(L); + + return 2; + } + lua_pushboolean(L, FALSE); return 1;