From 0ea601127eb0069b9f04382120526413763cdaf9 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Thu, 22 Jan 2026 14:40:45 +0100 Subject: [PATCH] BUG/MAJOR: applet: Don't call I/O handler if the applet was shut In 3.0, it was stated an applet could not be woken up after it was shutdown. So the corresponding test in the applets I/O handler was removed. However, it seems it may happen, especially when outgoing data are blocked on the opposite side. But it is really unexpected because the "release" callback function was already called and the appctx context was most probably released. Strangely, it was never detected by any applet till now. But the Prometheus exporter was never updated and was still testing the shutdown. But when it was refactored to use the new applet API in 3.3, the test was removed. And this introduced a regression leading a crash because a server object could be corrupted. Conditions to hit the bug are not really clear however. So, now, to avoid any issue with all other applets, the test is performed in task_process_applet(). The I/O handler is no longer called if the applet is already shut. The same is performed for applets still relying on the old API. An amazing thanks to @idl0r for his invaluable help on this issue ! This patch should fix the issue #3244. It should first be backported to 3.3 and then slowly as far as 3.0. --- src/applet.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/applet.c b/src/applet.c index 75d714c9b..de555c325 100644 --- a/src/applet.c +++ b/src/applet.c @@ -848,7 +848,12 @@ struct task *task_run_applet(struct task *t, void *context, unsigned int state) input = applet_output_data(app); output = co_data(oc); - app->applet->fct(app); + + /* Don't call I/O handler if the applet was shut (release callback was + * already called) + */ + if (se_fl_test(app->sedesc, SE_FL_SHR | SE_FL_SHW)) + app->applet->fct(app); TRACE_POINT(APPLET_EV_PROCESS, app); @@ -945,7 +950,11 @@ struct task *task_process_applet(struct task *t, void *context, unsigned int sta applet_need_more_data(app); applet_have_no_more_data(app); - app->applet->fct(app); + /* Don't call I/O handler if the applet was shut (release callback was + * already called) + */ + if (!applet_fl_test(app, APPCTX_FL_SHUTDOWN)) + app->applet->fct(app); TRACE_POINT(APPLET_EV_PROCESS, app);