diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2021-10-20 14:54:01 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2021-10-20 14:54:01 +0100 |
commit | 650d1d98463469738e6cf83cc8ea6a70aa220785 (patch) | |
tree | f21a6e4ba0b0a1d921c1b5af57bf5f8b2a430efd /src | |
parent | 235488eac67f055eee9246191ab70eb80fd81a1e (diff) | |
download | rspamd-650d1d98463469738e6cf83cc8ea6a70aa220785.tar.gz rspamd-650d1d98463469738e6cf83cc8ea6a70aa220785.zip |
[Minor] Add a hack to fix termination race condition
Diffstat (limited to 'src')
-rw-r--r-- | src/libserver/fuzzy_backend/fuzzy_backend_redis.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/src/libserver/fuzzy_backend/fuzzy_backend_redis.c b/src/libserver/fuzzy_backend/fuzzy_backend_redis.c index 18e049926..efed2fea2 100644 --- a/src/libserver/fuzzy_backend/fuzzy_backend_redis.c +++ b/src/libserver/fuzzy_backend/fuzzy_backend_redis.c @@ -58,6 +58,7 @@ struct rspamd_fuzzy_backend_redis { struct rspamd_redis_pool *pool; gdouble timeout; gint conf_ref; + bool terminated; ref_entry_t ref; }; @@ -170,10 +171,8 @@ rspamd_fuzzy_redis_session_dtor (struct rspamd_fuzzy_redis_session *session, static void rspamd_fuzzy_backend_redis_dtor (struct rspamd_fuzzy_backend_redis *backend) { - lua_State *L = backend->L; - - if (backend->conf_ref != -1) { - luaL_unref (L, LUA_REGISTRYINDEX, backend->conf_ref); + if (!backend->terminated && backend->conf_ref != -1) { + luaL_unref (backend->L, LUA_REGISTRYINDEX, backend->conf_ref); } if (backend->id) { @@ -1641,5 +1640,17 @@ rspamd_fuzzy_backend_close_redis (struct rspamd_fuzzy_backend *bk, g_assert (backend != NULL); + /* + * XXX: we leak lua registry element there to avoid crashing + * due to chicken-egg problem between lua state termination and + * redis pool termination. + * Here, we assume that redis pool is destroyed AFTER lua_state, + * so all connections pending will release references but due to + * `terminated` hack they will not try to access Lua stuff + * This is enabled merely if we have connections pending (e.g. refcount > 1) + */ + if (backend->ref.refcount > 1) { + backend->terminated = true; + } REF_RELEASE (backend); } |