From fff876003b28ccbde3f275f3795ac9149031c426 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 31 Jan 2016 11:10:24 +0000 Subject: [PATCH] dix/touch: Avoid overallocating event list for TouchOwnershipEvent There can only be a single touch ownership event, and the allocation for the full event list is often the first victim to an out-of-memory condition (since it trips over with FatalError). By noting we only need a single event, we can allocate the small struct on the stack and delay the inevitable. References: https://bugs.freedesktop.org/show_bug.cgi?id=93720 Signed-off-by: Chris Wilson --- Xi/exevents.c | 12 ++++-------- dix/getevents.c | 26 ++++++++++++-------------- dix/touch.c | 33 ++++++++++----------------------- include/input.h | 8 ++++---- 4 files changed, 30 insertions(+), 49 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 1c586d0..9d2c380 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -989,14 +989,10 @@ static void TouchSendOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, int reason, XID resource) { - int nev, i; - InternalEvent *tel = InitEventList(GetMaximumEventsNum()); - - nev = GetTouchOwnershipEvents(tel, dev, ti, reason, resource, 0); - for (i = 0; i < nev; i++) - mieqProcessDeviceEvent(dev, tel + i, NULL); - - FreeEventList(tel, GetMaximumEventsNum()); + InternalEvent *tel = InitEventList(1); + if (GetTouchOwnershipEvent(tel, dev, ti, reason, resource, 0)) + mieqProcessDeviceEvent(dev, tel, NULL); + FreeEventList(tel, 1); } /** diff --git a/dix/getevents.c b/dix/getevents.c index fa5890e..c281bc3 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -1811,25 +1811,23 @@ GetProximityEvents(InternalEvent *events, DeviceIntPtr pDev, int type, } int -GetTouchOwnershipEvents(InternalEvent *events, DeviceIntPtr pDev, - TouchPointInfoPtr ti, uint8_t reason, XID resource, - uint32_t flags) +GetTouchOwnershipEvent(InternalEvent *event, DeviceIntPtr pDev, + TouchPointInfoPtr ti, uint8_t reason, XID resource, + uint32_t flags) { - TouchClassPtr t = pDev->touch; - TouchOwnershipEvent *event; - CARD32 ms = GetTimeInMillis(); + TouchOwnershipEvent *toe; - if (!pDev->enabled || !t || !ti) + if (!pDev->enabled || !pDev->touch || !ti) return 0; - event = &events->touch_ownership_event; - init_touch_ownership(pDev, event, ms); + toe = &event->touch_ownership_event; + init_touch_ownership(pDev, toe, GetTimeInMillis()); - event->touchid = ti->client_id; - event->sourceid = ti->sourceid; - event->resource = resource; - event->flags = flags; - event->reason = reason; + toe->touchid = ti->client_id; + toe->sourceid = ti->sourceid; + toe->resource = resource; + toe->flags = flags; + toe->reason = reason; return 1; } diff --git a/dix/touch.c b/dix/touch.c index 49d16ab..c8309cc 100644 --- a/dix/touch.c +++ b/dix/touch.c @@ -972,11 +972,7 @@ TouchListenerGone(XID resource) { TouchPointInfoPtr ti; DeviceIntPtr dev; - InternalEvent *events = InitEventList(GetMaximumEventsNum()); - int i, j, k, nev; - - if (!events) - FatalError("TouchListenerGone: couldn't allocate events\n"); + int i, j; for (dev = inputInfo.devices; dev; dev = dev->next) { if (!dev->touch) @@ -988,29 +984,26 @@ TouchListenerGone(XID resource) continue; for (j = 0; j < ti->num_listeners; j++) { + InternalEvent event; + if (CLIENT_BITS(ti->listeners[j].listener) != resource) continue; - nev = GetTouchOwnershipEvents(events, dev, ti, XIRejectTouch, - ti->listeners[j].listener, 0); - for (k = 0; k < nev; k++) - mieqProcessDeviceEvent(dev, events + k, NULL); - + GetTouchOwnershipEvent(&event, dev, ti, XIRejectTouch, + ti->listeners[j].listener, 0); + mieqProcessDeviceEvent(dev, &event, NULL); break; } } } - - FreeEventList(events, GetMaximumEventsNum()); } int TouchListenerAcceptReject(DeviceIntPtr dev, TouchPointInfoPtr ti, int listener, int mode) { - InternalEvent *events; + InternalEvent event; int nev; - int i; BUG_RETURN_VAL(listener < 0, BadMatch); BUG_RETURN_VAL(listener >= ti->num_listeners, BadMatch); @@ -1024,17 +1017,11 @@ TouchListenerAcceptReject(DeviceIntPtr dev, TouchPointInfoPtr ti, int listener, return Success; } - events = InitEventList(GetMaximumEventsNum()); - BUG_RETURN_VAL_MSG(!events, BadAlloc, "Failed to allocate touch ownership events\n"); - - nev = GetTouchOwnershipEvents(events, dev, ti, mode, - ti->listeners[0].listener, 0); + nev = GetTouchOwnershipEvent(&event, dev, ti, mode, + ti->listeners[0].listener, 0); BUG_WARN_MSG(nev == 0, "Failed to get touch ownership events\n"); - for (i = 0; i < nev; i++) - mieqProcessDeviceEvent(dev, events + i, NULL); - - FreeEventList(events, GetMaximumEventsNum()); + mieqProcessDeviceEvent(dev, &event, NULL); return nev ? Success : BadMatch; } diff --git a/include/input.h b/include/input.h index d8bd9c6..90d4c18 100644 --- a/include/input.h +++ b/include/input.h @@ -465,10 +465,10 @@ void QueueTouchEvents(DeviceIntPtr device, uint32_t ddx_touchid, int flags, const ValuatorMask *mask); -extern int GetTouchOwnershipEvents(InternalEvent *events, - DeviceIntPtr pDev, - TouchPointInfoPtr ti, - uint8_t mode, XID resource, uint32_t flags); +extern int GetTouchOwnershipEvent(InternalEvent *event, + DeviceIntPtr pDev, + TouchPointInfoPtr ti, + uint8_t mode, XID resource, uint32_t flags); extern void GetDixTouchEnd(InternalEvent *ievent, DeviceIntPtr dev, -- 2.7.0