xpra icon
Bug tracker and wiki

Ticket #475: xshm-fixleak+debug.patch

File xshm-fixleak+debug.patch, 11.5 KB (added by Antoine Martin, 7 years ago)

fixes the leak and adds some debug

  • xpra/x11/bindings/ximage.pyx

     
    4343        pass
    4444    key_t IPC_PRIVATE
    4545    int IPC_CREAT
     46    int IPC_RMID
    4647
    4748cdef extern from "sys/shm.h":
    4849    int shmget(key_t __key, size_t __size, int __shmflg)
    4950    void *shmat(int __shmid, const void *__shmaddr, int __shmflg)
    5051    int shmdt (const void *__shmaddr)
     52    ctypedef struct shmid_ds:
     53        pass
     54    int shmctl(int shmid, int cmd, shmid_ds *buf)
    5155
    5256cdef extern from "errno.h" nogil:
    5357    int errno
     
    99103        int map_entries
    100104
    101105
     106    void XSync(Display * display, Bool discard)
     107
    102108    int XFree(void * data)
    103109
    104110    Bool XQueryExtension(Display * display, char *name,
     
    335341            free(self.pixels)
    336342            self.pixels = NULL
    337343
     344from xpra.util import AtomicInteger
     345xshm_counter = AtomicInteger()
    338346
    339347cdef class XShmWrapper(object):
    340348    cdef Display *display                              #@DuplicatedSignature
     
    347355    cdef XImage *image
    348356    cdef int ref_count
    349357    cdef Bool closed
     358    cdef int unique_id
    350359
    351360    cdef init(self, Display *display, Window xwindow, Visual *visual, int width, int height, int depth):
    352361        self.display = display
     
    355364        self.width = width
    356365        self.height = height
    357366        self.depth = depth
     367        self.unique_id = xshm_counter.increase()
    358368
    359369    def setup(self):
    360370        #returns:
     
    367377        self.image = XShmCreateImage(self.display, self.visual, self.depth,
    368378                          ZPixmap, NULL, &self.shminfo,
    369379                          self.width, self.height)
    370         xshm_debug("XShmWrapper.XShmCreateImage(%sx%s-%s) %s", self.width, self.height, self.depth, self.image!=NULL)
     380        xshm_debug("XShmWrapper.XShmCreateImage(%sx%s-%s) %s ID=%s", self.width, self.height, self.depth, self.image!=NULL, self.unique_id)
    371381        if self.image==NULL:
    372382            log.error("XShmWrapper.XShmCreateImage(%sx%s-%s) failed!", self.width, self.height, self.depth)
    373383            self.cleanup()
     
    416426        assert self.image!=NULL, "cannot retrieve image wrapper: XImage is NULL!"
    417427        if self.closed:
    418428            return None
    419         xshm_debug("XShmWrapper.get_image%s", (xpixmap, x, y, w, h))
     429        xshm_debug("XShmWrapper.get_image%s ID=%s", (xpixmap, x, y, w, h), self.unique_id)
    420430        if x>=self.width or y>=self.height:
    421431            xshm_debug("XShmWrapper.get_pixels(%s, %s, %s, %s) position outside image dimensions %sx%s", x, y, w, h, self.width, self.height)
    422432            return None
     
    445455        #and they will point to our Image XShm area.
    446456        #so we have to wait until *they* are freed,
    447457        #and rely on them telling us via the free_image callback.
    448         xshm_debug("XShmWrapper.cleanup() ref_count=%s", self.ref_count)
     458        xshm_debug("XShmWrapper.cleanup() ID=%s, ref_count=%s", self.unique_id, self.ref_count)
    449459        self.closed = True
    450460        if self.ref_count==0:
    451461            self.free()
    452462
    453463    def free_image(self):                               #@DuplicatedSignature
    454464        self.ref_count -= 1
    455         xshm_debug("XShmWrapper.free_image() closed=%s, new ref_count=%s", self.closed, self.ref_count)
     465        xshm_debug("XShmWrapper.free_image() ID=%s, closed=%s, new ref_count=%s", self.unique_id, self.closed, self.ref_count)
    456466        if self.closed and self.ref_count==0:
    457467            self.free()
    458468
     
    460470        assert self.ref_count==0, "XShmWrapper %s cannot be freed: still has a ref count of %s" % (self, self.ref_count)
    461471        assert self.closed, "XShmWrapper %s cannot be freed: it is not closed yet" % self
    462472        has_shm = self.shminfo.shmaddr!=<char *> -1
    463         xshm_debug("XShmWrapper.free() has_shm=%s", has_shm)
     473        xshm_debug("XShmWrapper.free() ID=%s, has_shm=%s", self.unique_id, has_shm)
    464474        if has_shm:
    465475            XShmDetach(self.display, &self.shminfo)
     476        xshm_debug("XShmWrapper.free() ID=%s, image=%s", self.unique_id, hex(<unsigned long> self.image))
     477        if self.image!=NULL:
     478            XDestroyImage(self.image)
     479            self.image = NULL
     480            XSync(self.display, False)
    466481        if has_shm:
     482            shmctl(self.shminfo.shmid, IPC_RMID, NULL)
    467483            shmdt(self.shminfo.shmaddr)
    468484            self.shminfo.shmaddr = <char *> -1
    469         if self.image!=NULL:
    470             XDestroyImage(self.image)
    471             self.image = NULL
     485            self.shminfo.shmid = -1
     486            XSync(self.display, False)
    472487
     488xshm_image_counter = AtomicInteger()
    473489
    474490cdef class XShmImageWrapper(XImageWrapper):
    475491
    476492    cdef object free_callback
     493    cdef int unique_id                              #@DuplicatedSignature
    477494
    478495    def __init__(self, *args):                      #@DuplicatedSignature
    479496        self.free_callback = None
     497        self.unique_id = xshm_image_counter.increase()
    480498
    481499    def __str__(self):                              #@DuplicatedSignature
    482         return "XShmImageWrapper(%s: %s, %s, %s, %s)" % (self.pixel_format, self.x, self.y, self.width, self.height)
     500        return "XShmImageWrapper(%s: %s, %s, %s, %s, ID=%s)" % (self.pixel_format, self.x, self.y, self.width, self.height, self.unique_id)
    483501
    484502    def get_image_pixels(self):                     #@DuplicatedSignature
    485503        cdef char *offset
     
    490508        return PyBuffer_FromReadWriteMemory(offset, self.get_size())
    491509
    492510    def free(self):                                 #@DuplicatedSignature
    493         xshm_debug("XShmImageWrapper.free() free_callback=%s", self.free_callback)
     511        xshm_debug("XShmImageWrapper.free() ID=%s, free_callback=%s", self.unique_id, self.free_callback)
    494512        #ensure we never try to XDestroyImage:
    495513        self.image = NULL
    496514        self.free_pixels()
     
    498516            cb = self.free_callback
    499517            self.free_callback = None
    500518            cb()
    501         xshm_debug("XShmImageWrapper.free() done")
     519        xshm_debug("XShmImageWrapper.free() ID=%s, done", self.unique_id)
    502520
    503521    def set_free_callback(self, callback):
    504522        self.free_callback = callback
     
    528546
    529547    def get_image(self, x, y, width, height):                #@DuplicatedSignature
    530548        if self.pixmap is None:
    531             log.warn("PixmapWrapper.get_image(%s, %s, %s, %s) pixmap=%s", x, y, width, height, self.pixmap)
     549            log.warn("PixmapWrapper.get_image(%s, %s, %s, %s) ID=%s, pixmap=%s", x, y, width, height, self.unique_id, self.pixmap)
    532550            return  None
    533         debug("PixmapWrapper.get_image(%s, %s, %s, %s) pixmap=%s, width=%s, height=%s", x, y, width, height, self.pixmap, self.width, self.height)
     551        debug("PixmapWrapper.get_image(%s, %s, %s, %s) ID=%s, pixmap=%s, width=%s, height=%s", x, y, width, height, self.unique_id, self.pixmap, self.width, self.height)
    534552        if x>=self.width or y>=self.height:
    535553            debug("PixmapWrapper.get_image(%s, %s, %s, %s) position outside image dimensions %sx%s", x, y, width, height, self.width, self.height)
    536554            return None
     
    542560        return get_image(self.display, self.pixmap, x, y, width, height)
    543561
    544562    def __del__(self):
    545         debug("PixmapWrapper.__del__() pixmap=%s", self.pixmap)
     563        debug("PixmapWrapper.__del__() ID=%s, pixmap=%s", self.unique_id, self.pixmap)
    546564        if self.pixmap!=0:
    547565            XFreePixmap(self.display, self.pixmap)
    548566            self.pixmap = 0
  • xpra/x11/gtk_x11/composite.py

     
    8282            trap.swallow_synced(X11Window.XDamageDestroy, self._damage_handle)
    8383            self._damage_handle = None
    8484        if self._shm_handle:
    85             self._shm_handle.cleanup()
     85            trap.swallow_synced(self._shm_handle.cleanup)
    8686            self._shm_handle = None
    8787        #note: this should be redundant since we cleared the
    8888        #reference to self._window and shortcut out in do_get_property_contents_handle
  • xpra/x11/gtk_x11/error.py

     
    102102            self._enter()
    103103            value = fun(*args, **kwargs)
    104104        except Exception, e:
     105            log.error("Exception: %s", e)
    105106            if XPRA_X11_DEBUG:
    106107                log.error("_call(%s,%s,%s,%s) %s", need_sync, fun, args, kwargs, e, exc_info=True)
    107108            else:
  • xpra/x11/gtk_x11/window.py

     
    371371            self._property_handlers[name](self)
    372372
    373373    def do_xpra_configure_event(self, event):
     374        log("BaseWindowModel.do_xpra_configure_event(%s) client_window=%s, managed=%s", event, self.client_window, self._managed)
    374375        if self.client_window is None or not self._managed:
    375376            return
    376377        oldgeom = self._geometry
     
    10171018        self._internal_set_property("user-friendly-size", (wvis, hvis))
    10181019
    10191020    def do_xpra_configure_event(self, event):
    1020         log("WindowModel.do_xpra_configure_event(%s)", event)
     1021        log.info("WindowModel.do_xpra_configure_event(%s) managed=%s", event, self._managed)
    10211022        if not self._managed:
    10221023            return
    10231024        BaseWindowModel.do_xpra_configure_event(self, event)
    10241025        if self.corral_window is None or not self.corral_window.is_visible():
     1026            log.info("corral_window not visible")
    10251027            return
    10261028        if self.client_window is None or not self.client_window.is_visible():
     1029            log.info("client_window not visible")
    10271030            return
    10281031        try:
    10291032            #workaround applications whose windows disappear from underneath us:
     
    10331036            log.warn("failed to resize corral window: %s", e)
    10341037
    10351038    def resize_corral_window(self):
     1039        log.info("resize_corral_window()")
    10361040        #the client window may have been resized (generally programmatically)
    10371041        #so we may need to update the corral_window to match
    10381042        cow, coh = self.corral_window.get_geometry()[2:4]
     1043        log.info("corral window geometry: %s", (cow, coh))
    10391044        clx, cly, clw, clh = self.client_window.get_geometry()[:4]
     1045        log.info("client window geometry: %s", (clx, cly, clw, clh))
    10401046        if (clx, cly) != (0, 0):
    1041             log("resize_corral_window() client window has moved, resetting it")
     1047            log.info("resize_corral_window() client window has moved, resetting it")
    10421048            self.client_window.move(0, 0)
    10431049        if cow!=clw or coh!=clh:
    1044             log("resize_corral_window() corral window (%sx%s) does not match client window (%sx%s), resizing it",
     1050            log.info("resize_corral_window() corral window (%sx%s) does not match client window (%sx%s), resizing it",
    10451051                     cow, coh, clw, clh)
    10461052            self.corral_window.resize(clw, clh)
    10471053            hints = self.get_property("size-hints")
    10481054            self._sanitize_size_hints(hints)
    10491055            size = calc_constrained_size(clw, clh, hints)
    1050             log("resize_corral_window() new constrained size=%s", size)
     1056            log.info("resize_corral_window() new constrained size=%s", size)
    10511057            w, h, wvis, hvis = size
    10521058            self._internal_set_property("actual-size", (w, h))
    10531059            self._internal_set_property("user-friendly-size", (wvis, hvis))