223 lines
6.5 KiB
Diff
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
|
|
|