Re: pixbuf leakage

"Walter C. Pelissero" <[email protected]> Fri, 23 May 2008 15:54:43 +0200
Newsgroups gmane.lisp.clg.devel
Message-ID <[email protected]>
Espen S Johnsen writes:
 > But it suddenly occurred to me why this code is leaking memory. The
 > signal handler closures keep references to the loader object, which
 > prevents the ref count from reaching zero and thus freeing the
 > object. I don't think it is possibly avoid this, but there are two
 > ways to work around the problem. One is to disconnect the signal
 > handlers when loader is not used any more. The other is to give the
 > loader object as the first argument to the callback functions with
 > the object keyword argument to signal-connect (this requires the
 > latest code from CVS due to a couple of bugs in earlier code).

Well the generalised solution to the problem was easier than I
thought.  (Without messing with the C library at all.)

In the following form it's just an add-on (actually a mixin) to avoid
disrupting the CLG code, but I don't think it should be difficult to
hack, say, gobject itself.


(defclass signalled-mixin ()
  ((signal-handlers :type list
		    :initform '())))

(defmethod signal-connect ((object signalled-mixin) signal function &key &allow-other-keys)
  (declare (ignore signal function))
  (let ((handler-id (call-next-method)))
    (push handler-id (slot-value object 'signal-handlers))
    handler-id))

(defmethod disconnect-all-signal-handlers ((object signalled-mixin))
  (with-slots (signal-handlers) object
    (dolist (handler-id signal-handlers)
      (glib:signal-handler-disconnect object handler-id))
    (setf signal-handlers '())))

(defmethod object-destroy-signal ((object glib:gobject))
  ;; this is the default although gobject itself doesn't accept this
  ;; signal, neither are its subclasses required to do so
  'destroy)

(defmethod initialize-instance ((object signalled-mixin) &key &allow-other-keys)
  (call-next-method)
  (signal-connect object (object-destroy-signal object)
		  #'(lambda (object)
		      (disconnect-all-signal-handlers object))
		  :object t))


To make use of that, the test code needs the following:

(defclass my-pixbuf-loader (signalled-mixin gdk:pixbuf-loader)
  ()
  (:metaclass glib:gobject-class))

(defmethod object-destroy-signal ((object my-pixbuf-loader))
  'closed)

and thus instantiate my-pixbuf-loader instead of pixbuf-loader.

-- 
walter pelissero
http://www.pelissero.de

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/