From 14e029d1e0d3b1b9e1981bcca84ecf765e4ed738 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 16 Nov 2018 14:36:55 -0500 Subject: [PATCH xserver] dix: ensure work queues are cleared on reset If the server resets, most client workqueues are cleaned up as the clients are killed. The one exception is the server's client, which is exempt from the killing spree. If that client has a queued work procedure active, it won't get cleared on reset. This commit ensures it gets cleared too. --- dix/dixutils.c | 13 +++++++++++++ dix/main.c | 2 ++ include/dix.h | 2 ++ 3 files changed, 17 insertions(+) diff --git a/dix/dixutils.c b/dix/dixutils.c index 540023cbd..a4e27fe27 100644 --- a/dix/dixutils.c +++ b/dix/dixutils.c @@ -480,60 +480,73 @@ RemoveBlockAndWakeupHandlers(ServerBlockHandlerProcPtr blockHandler, if (inHandler) { handlerDeleted = TRUE; handlers[i].deleted = TRUE; } else { for (; i < numHandlers - 1; i++) handlers[i] = handlers[i + 1]; numHandlers--; } break; } } void InitBlockAndWakeupHandlers(void) { free(handlers); handlers = (BlockHandlerPtr) 0; numHandlers = 0; sizeHandlers = 0; } /* * A general work queue. Perform some task before the server * sleeps for input. */ WorkQueuePtr workQueue; static WorkQueuePtr *workQueueLast = &workQueue; +void +ClearWorkQueue(void) +{ + WorkQueuePtr q, *p; + + p = &workQueue; + while ((q = *p)) { + *p = q->next; + free(q); + } + workQueueLast = p; +} + void ProcessWorkQueue(void) { WorkQueuePtr q, *p; p = &workQueue; /* * Scan the work queue once, calling each function. Those * which return TRUE are removed from the queue, otherwise * they will be called again. This must be reentrant with * QueueWorkProc. */ while ((q = *p)) { if ((*q->function) (q->client, q->closure)) { /* remove q from the list */ *p = q->next; /* don't fetch until after func called */ free(q); } else { p = &q->next; /* don't fetch until after func called */ } } workQueueLast = p; } void ProcessWorkQueueZombies(void) { WorkQueuePtr q, *p; diff --git a/dix/main.c b/dix/main.c index f98643aa5..b228d9c28 100644 --- a/dix/main.c +++ b/dix/main.c @@ -315,46 +315,48 @@ dix_main(int argc, char *argv[], char *envp[]) dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN); free(pScreen); screenInfo.numGPUScreens = i; } for (i = screenInfo.numScreens - 1; i >= 0; i--) { FreeScratchPixmapsForScreen(screenInfo.screens[i]); FreeGCperDepth(i); FreeDefaultStipple(i); dixFreeScreenSpecificPrivates(screenInfo.screens[i]); (*screenInfo.screens[i]->CloseScreen) (screenInfo.screens[i]); dixFreePrivates(screenInfo.screens[i]->devPrivates, PRIVATE_SCREEN); free(screenInfo.screens[i]); screenInfo.numScreens = i; } ReleaseClientIds(serverClient); dixFreePrivates(serverClient->devPrivates, PRIVATE_CLIENT); serverClient->devPrivates = NULL; dixFreeRegistry(); FreeFonts(); FreeAllAtoms(); FreeAuditTimer(); DeleteCallbackManager(); + ClearWorkQueue(); + if (dispatchException & DE_TERMINATE) { CloseWellKnownConnections(); } OsCleanup((dispatchException & DE_TERMINATE) != 0); if (dispatchException & DE_TERMINATE) { ddxGiveUp(EXIT_NO_ERROR); break; } free(ConnectionInfo); ConnectionInfo = NULL; } return 0; } diff --git a/include/dix.h b/include/dix.h index 476559842..b6e2bcfde 100644 --- a/include/dix.h +++ b/include/dix.h @@ -213,60 +213,62 @@ extern _X_EXPORT int AlterSaveSetForClient(ClientPtr /*client */ , Bool /*map */ ); extern _X_EXPORT void DeleteWindowFromAnySaveSet(WindowPtr /*pWin */ ); extern _X_EXPORT void BlockHandler(void *timeout); extern _X_EXPORT void WakeupHandler(int result); void EnableLimitedSchedulingLatency(void); void DisableLimitedSchedulingLatency(void); typedef void (*ServerBlockHandlerProcPtr) (void *blockData, void *timeout); typedef void (*ServerWakeupHandlerProcPtr) (void *blockData, int result); extern _X_EXPORT Bool RegisterBlockAndWakeupHandlers(ServerBlockHandlerProcPtr blockHandler, ServerWakeupHandlerProcPtr wakeupHandler, void *blockData); extern _X_EXPORT void RemoveBlockAndWakeupHandlers(ServerBlockHandlerProcPtr blockHandler, ServerWakeupHandlerProcPtr wakeupHandler, void *blockData); extern _X_EXPORT void InitBlockAndWakeupHandlers(void); +extern _X_EXPORT void ClearWorkQueue(void); + extern _X_EXPORT void ProcessWorkQueue(void); extern _X_EXPORT void ProcessWorkQueueZombies(void); extern _X_EXPORT Bool QueueWorkProc(Bool (*function)(ClientPtr clientUnused, void *closure), ClientPtr client, void *closure); typedef Bool (*ClientSleepProcPtr) (ClientPtr client, void *closure); extern _X_EXPORT Bool ClientSleep(ClientPtr client, ClientSleepProcPtr function, void *closure); #ifndef ___CLIENTSIGNAL_DEFINED___ #define ___CLIENTSIGNAL_DEFINED___ extern _X_EXPORT Bool ClientSignal(ClientPtr /*client */ ); #endif /* ___CLIENTSIGNAL_DEFINED___ */ #ifndef ___CLIENTSIGNALALL_DEFINED___ #define ___CLIENTSIGNALALL_DEFINED___ #define CLIENT_SIGNAL_ANY ((void *)-1) extern _X_EXPORT int ClientSignalAll(ClientPtr /*client*/, ClientSleepProcPtr /*function*/, void * /*closure*/); #endif /* ___CLIENTSIGNALALL_DEFINED___ */ extern _X_EXPORT void ClientWakeup(ClientPtr /*client */ ); -- 2.17.1