From 48ca8adc6dd020ba503294ca245d32fc6ecdb6e7 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Wed, 23 Apr 2025 19:59:06 +0200 Subject: [PATCH] dix: make DeleteCallbackList() non-static and document it Allow using it by other places outside this file, so we can also support callback lists in dynamically allocated structures: Those cases need to explicitly call DeleteCallbackList() before free()ing the structures - otherwise we're getting heap corruptions, because the actual deletion can happen asynchronously. Signed-off-by: Enrico Weigelt, metux IT consult --- dix/callback_priv.h | 11 +++++++++++ dix/dixutils.c | 20 ++++++-------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/dix/callback_priv.h b/dix/callback_priv.h index 828b74cf2..9f1022ef6 100644 --- a/dix/callback_priv.h +++ b/dix/callback_priv.h @@ -10,4 +10,15 @@ void InitCallbackManager(void); void DeleteCallbackManager(void); +/* + * @brief delete a callback list + * + * Calling this is necessary if a CallbackListPtr is used inside a dynamically + * allocated structure, before it is freed. If it's not done, memory corruption + * or segfault can happen at a much later point (eg. next server incarnation) + * + * @param pcbl pointer to the list head (CallbackListPtr) + */ +void DeleteCallbackList(CallbackListPtr *pcbl); + #endif /* _XSERVER_CALLBACK_PRIV_H */ diff --git a/dix/dixutils.c b/dix/dixutils.c index 359244883..b3708cec9 100644 --- a/dix/dixutils.c +++ b/dix/dixutils.c @@ -693,8 +693,6 @@ _DeleteCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, void *data) return FALSE; } -static void DeleteCallbackList(CallbackListPtr *pcbl); - void _CallCallbacks(CallbackListPtr *pcbl, void *call_data) { @@ -745,25 +743,26 @@ _CallCallbacks(CallbackListPtr *pcbl, void *call_data) } } -static void -_DeleteCallbackList(CallbackListPtr *pcbl) +void DeleteCallbackList(CallbackListPtr *pcbl) { + if (!pcbl || !*pcbl) + return; + CallbackListPtr cbl = *pcbl; - CallbackPtr cbr, nextcbr; - int i; if (cbl->inCallback) { cbl->deleted = TRUE; return; } - for (i = 0; i < numCallbackListsToCleanup; i++) { + for (int i = 0; i < numCallbackListsToCleanup; i++) { if (listsToCleanup[i] == pcbl) { listsToCleanup[i] = NULL; break; } } + CallbackPtr cbr, nextcbr; for (cbr = cbl->list; cbr != NULL; cbr = nextcbr) { nextcbr = cbr->next; free(cbr); @@ -827,13 +826,6 @@ DeleteCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, void *data) return _DeleteCallback(pcbl, callback, data); } -static void DeleteCallbackList(CallbackListPtr *pcbl) -{ - if (!pcbl || !*pcbl) - return; - _DeleteCallbackList(pcbl); -} - void DeleteCallbackManager(void) {