Xext: store the GenericMasks in the resource system.
This fixes a severe issue - when the client died the event mask didn't get unregistered and a future event would dereference dangling pointers. By storing the event masks in the resource system we can free them when the client dies.
This commit is contained in:
parent
db86b8839f
commit
acce270935
53
Xext/geext.c
53
Xext/geext.c
|
@ -36,12 +36,15 @@
|
|||
#define SERVER_GE_MAJOR 1
|
||||
#define SERVER_GE_MINOR 0
|
||||
|
||||
#define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
|
||||
|
||||
int GEEventBase;
|
||||
int GEErrorBase;
|
||||
DevPrivateKey GEClientPrivateKey = &GEClientPrivateKey;
|
||||
int GEEventType; /* The opcode for all GenericEvents will have. */
|
||||
|
||||
int RT_GECLIENT = 0;
|
||||
|
||||
|
||||
GEExtension GEExtensions[MAXEXTENSIONS];
|
||||
|
||||
|
@ -53,6 +56,7 @@ static const int version_requests[] = {
|
|||
|
||||
/* Forward declarations */
|
||||
static void SGEGenericEvent(xEvent* from, xEvent* to);
|
||||
static void GERecalculateWinMask(WindowPtr pWin);
|
||||
|
||||
#define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0]))
|
||||
|
||||
|
@ -211,6 +215,43 @@ SGEGenericEvent(xEvent* from, xEvent* to)
|
|||
GEExtensions[gefrom->extension & 0x7F].evswap(gefrom, geto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resource callback, invoked when the client disconnects and the associated
|
||||
* GE masks must be destroyed.
|
||||
*/
|
||||
int
|
||||
GEClientGone(WindowPtr pWin, XID id)
|
||||
{
|
||||
GenericClientMasksPtr gclmask;
|
||||
GenericMaskPtr gmask, prev = NULL;
|
||||
|
||||
if (!pWin || !pWin->optional)
|
||||
return Success;
|
||||
|
||||
gclmask = pWin->optional->geMasks;
|
||||
for (gmask = gclmask->geClients; gmask; gmask = gmask->next)
|
||||
{
|
||||
if (gmask->resource == id)
|
||||
{
|
||||
if (prev)
|
||||
{
|
||||
prev->next = gmask->next;
|
||||
xfree(gmask);
|
||||
} else {
|
||||
gclmask->geClients = NULL;
|
||||
CheckWindowOptionalNeed(pWin);
|
||||
GERecalculateWinMask(pWin);
|
||||
xfree(gmask);
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
prev = gmask;
|
||||
}
|
||||
|
||||
FatalError("Client not a GE client");
|
||||
return BadImplementation;
|
||||
}
|
||||
|
||||
/* Init extension, register at server.
|
||||
* Since other extensions may rely on XGE (XInput does already), it is a good
|
||||
* idea to init XGE first, before any other extension.
|
||||
|
@ -234,6 +275,9 @@ GEExtensionInit(void)
|
|||
GEErrorBase = extEntry->errorBase;
|
||||
GEEventType = GEEventBase;
|
||||
|
||||
RT_GECLIENT = CreateNewResourceType((DeleteType)GEClientGone);
|
||||
RegisterResourceName(RT_GECLIENT, "GECLIENT");
|
||||
|
||||
memset(GEExtensions, 0, sizeof(GEExtensions));
|
||||
|
||||
EventSwapVector[GenericEvent] = (EventSwapPtr) SGEGenericEvent;
|
||||
|
@ -338,7 +382,7 @@ GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev,
|
|||
cli = evmasks->geClients;
|
||||
while(cli)
|
||||
{
|
||||
if (cli->client == pClient && cli->dev == pDev)
|
||||
if (rClient(cli) == pClient && cli->dev == pDev)
|
||||
break;
|
||||
cli = cli->next;
|
||||
}
|
||||
|
@ -352,16 +396,17 @@ GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev,
|
|||
return;
|
||||
}
|
||||
cli->next = evmasks->geClients;
|
||||
cli->client = pClient;
|
||||
cli->resource = FakeClientID(pClient->index);
|
||||
cli->dev = pDev;
|
||||
evmasks->geClients = cli;
|
||||
AddResource(cli->resource, RT_GECLIENT, (pointer)pWin);
|
||||
}
|
||||
cli->eventMask[extension] = mask;
|
||||
} else
|
||||
{
|
||||
/* remove client. */
|
||||
cli = pWin->optional->geMasks->geClients;
|
||||
if (cli->client == pClient && cli->dev == pDev)
|
||||
if (rClient(cli) == pClient && cli->dev == pDev)
|
||||
{
|
||||
pWin->optional->geMasks->geClients = cli->next;
|
||||
xfree(cli);
|
||||
|
@ -372,7 +417,7 @@ GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev,
|
|||
|
||||
while(cli)
|
||||
{
|
||||
if (cli->client == pClient && cli->dev == pDev)
|
||||
if (rClient(cli) == pClient && cli->dev == pDev)
|
||||
{
|
||||
prev->next = cli->next;
|
||||
xfree(cli);
|
||||
|
|
|
@ -43,10 +43,10 @@ from the author.
|
|||
* A grab has only one instance of this struct.
|
||||
*/
|
||||
typedef struct _GenericMaskRec {
|
||||
ClientPtr client; /* client who set the event mask */
|
||||
struct _GenericMaskRec* next;
|
||||
XID resource; /* id for the resource manager */
|
||||
DeviceIntPtr dev;
|
||||
Mask eventMask[MAXEXTENSIONS]; /* one mask per extension */
|
||||
struct _GenericMaskRec* next;
|
||||
} GenericMaskRec, *GenericMaskPtr;
|
||||
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ ProcXExtendedGrabDevice(ClientPtr client)
|
|||
(XGenericEventMask*)(((XEventClass*)&stuff[1]) + stuff->event_count);
|
||||
|
||||
gemasks = xcalloc(1, sizeof(GenericMaskRec));
|
||||
gemasks->client = client;
|
||||
gemasks->resource = FakeClientID(client->index);
|
||||
gemasks->next = NULL;
|
||||
gemasks->eventMask[xgeMask->extension & 0x7F] = xgeMask->evmask;
|
||||
|
||||
|
|
14
dix/events.c
14
dix/events.c
|
@ -2118,7 +2118,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
|
|||
/* Handle generic events */
|
||||
if (type == GenericEvent)
|
||||
{
|
||||
GenericMaskPtr pClient;
|
||||
GenericMaskPtr gmask;
|
||||
/* We don't do more than one GenericEvent at a time. */
|
||||
if (count > 1)
|
||||
{
|
||||
|
@ -2132,16 +2132,16 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
|
|||
return 0;
|
||||
|
||||
/* run through all clients, deliver event */
|
||||
for (pClient = GECLIENT(pWin); pClient; pClient = pClient->next)
|
||||
for (gmask = GECLIENT(pWin); gmask; gmask = gmask->next)
|
||||
{
|
||||
if (pClient->eventMask[GEEXTIDX(pEvents)] & filter)
|
||||
if (gmask->eventMask[GEEXTIDX(pEvents)] & filter)
|
||||
{
|
||||
if (XaceHook(XACE_RECEIVE_ACCESS, pClient->client, pWin,
|
||||
if (XaceHook(XACE_RECEIVE_ACCESS, rClient(gmask), pWin,
|
||||
pEvents, count))
|
||||
/* do nothing */;
|
||||
else if (TryClientEvents(pClient->client, pDev,
|
||||
else if (TryClientEvents(rClient(gmask), pDev,
|
||||
pEvents, count,
|
||||
pClient->eventMask[GEEXTIDX(pEvents)],
|
||||
gmask->eventMask[GEEXTIDX(pEvents)],
|
||||
filter, grab) > 0)
|
||||
{
|
||||
deliveries++;
|
||||
|
@ -2223,7 +2223,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
|
|||
{
|
||||
GenericClientMasksPtr gemasks = pWin->optional->geMasks;
|
||||
GenericMaskPtr geclient = gemasks->geClients;
|
||||
while(geclient && geclient->client != client)
|
||||
while(geclient && rClient(geclient) != client)
|
||||
geclient = geclient->next;
|
||||
if (geclient)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue
Block a user