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) {