From 0901a82adbecdb2621efb481472aedc218f8fa4c Mon Sep 17 00:00:00 2001 From: Joshua Colp Date: Sat, 29 Aug 2015 12:36:35 -0300 Subject: [PATCH] taskprocessor: Fix race condition between unreferencing and finding. When unreferencing a taskprocessor its reference count is checked to determine if it should be unlinked from the taskprocessors container and its listener shut down. In between the time when the reference count is checked and unlinking it is possible for another thread to jump in, find it, and get a reference to it. If the thread then uses the taskprocessor it may find that it is not in the state it expects. This change locks the taskprocessors container during almost the entire unreference operation to ensure that any other thread which may attempt to find the taskprocessor has to wait. ASTERISK-25295 Change-Id: Icb842db82fe1cf238da55df92e95938a4419377c (cherry picked from commit a676ba2aad5525926ae31b8317b95ae52cbbabbb) --- main/taskprocessor.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/main/taskprocessor.c b/main/taskprocessor.c index 5fbbca571d..ad471a8adb 100644 --- a/main/taskprocessor.c +++ b/main/taskprocessor.c @@ -692,15 +692,25 @@ void *ast_taskprocessor_unreference(struct ast_taskprocessor *tps) return NULL; } + /* To prevent another thread from finding and getting a reference to this + * taskprocessor we hold the singletons lock. If we didn't do this then + * they may acquire it and find that the listener has been shut down. + */ + ao2_lock(tps_singletons); + if (ao2_ref(tps, -1) > 3) { + ao2_unlock(tps_singletons); return NULL; } + /* If we're down to 3 references, then those must be: * 1. The reference we just got rid of * 2. The container * 3. The listener */ - ao2_unlink(tps_singletons, tps); + ao2_unlink_flags(tps_singletons, tps, OBJ_NOLOCK); + ao2_unlock(tps_singletons); + listener_shutdown(tps->listener); return NULL; } -- 2.47.2