From cce2b0da954fb232cafc812ce5acd6f3b42341e9 Mon Sep 17 00:00:00 2001 From: Kevin Harwell Date: Mon, 27 Jan 2020 12:01:15 -0600 Subject: [PATCH] stasis/app: don't lock an app before a call to send Calling 'app_send' eventually calls the app's message handler. It's possible for a handler to obtain a lock on another object, and then need/want to lock the app object. If the caller of 'app_send' locks the app object prior to calling then there's a potential for a deadlock, if another thread calls 'app_send' without locking. This patch makes it so 'app_send' is not called with the app object locked in the section of code doing such. ASTERISK-28423 #close Change-Id: I6767c6d0933c7db1b984018966eefca4c0638a27 --- res/stasis/app.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/res/stasis/app.c b/res/stasis/app.c index aba2661400..ee2fd0bc52 100644 --- a/res/stasis/app.c +++ b/res/stasis/app.c @@ -1126,8 +1126,23 @@ void app_update(struct stasis_app *app, stasis_app_cb handler, void *data) "timestamp", ast_json_timeval(ast_tvnow(), NULL), "application", app->name); if (msg) { + /* + * The app must be unlocked before calling 'send' since a handler may + * subsequently attempt to grab the app lock after first obtaining a + * lock for another object, thus causing a deadlock. + */ + ao2_unlock(app); app_send(app, msg); + ao2_lock(app); ast_json_unref(msg); + if (!app->handler) { + /* + * If the handler disappeared then the app was deactivated. In that + * case don't replace. Re-activation will reset the handler later. + */ + ao2_unlock(app); + return; + } } } else { ast_verb(1, "Activating Stasis app '%s'\n", app->name);