xorg-x11-server/SOURCES/0001-dix-ensure-work-queues...

223 lines
6.5 KiB
Diff

From 14e029d1e0d3b1b9e1981bcca84ecf765e4ed738 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
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