When the I/O handler finishes reading the subprocess reply before
SIGCHLD arrives, neither handler would call rspamd_lua_cbdata_free:
the I/O handler skips cleanup because dead=FALSE, and the SIGCHLD
handler skips cleanup because replied=TRUE. This leaves the subprocess
in the main process workers table, causing shutdown to wait for a
child that has already exited.
Fix by always calling rspamd_lua_cbdata_free in the SIGCHLD handler
when replied=TRUE, since the I/O handler has already finished and
deferred cleanup to us.
"Worker has died without reply", NULL, 0);
rspamd_lua_cbdata_free(cbdata);
}
- /* If replied is TRUE, the I/O handler is processing the callback.
- * It will call rspamd_lua_cbdata_free() when done. */
+ else {
+ /* I/O handler already processed the reply but couldn't clean up
+ * because the child wasn't dead yet at that point. Clean up now. */
+ rspamd_lua_cbdata_free(cbdata);
+ }
/* We are done with this SIGCHLD */
return FALSE;