GDI resource leak in "custom draw" font handling ?

GDI resource leak in "custom draw" font handling ?

Post by Chris Uppa » Wed, 11 Feb 2004 17:41:47


I've just tracked down a GDI resource leak in my image and one app. I'm not
sure if the underlying problem is my code, or a bug in Dolphin, anyway here are
the details...

I've been using an idiom for making some elements of a list/tree draw
themselves in bold with code like:

ownerDrawElement: anNMLVCUSTOMDRAW
(...some condition...) ifTrue:
[anNMTVCUSTOMDRAW font beBold].

which works fine on the face of it, but turns out to cause a GDI resource leak.
The problem seems to be that Font>>beBold calls Font>>weight: which changes a
setting and then does a 'self free' to cause itself to be re-realised. As far
as I can tell, the #free is essentially a null-op since the font doesn't think
that it owns its handle, however it appears that Windows thinks that the font
created by NMVCUSTOMDRAW>>font *is* owned. Hence the resource leak.

I don't know if the above code snippet is how I'm *supposed* to get the effect,
but anyway I've changed it to read more like:

ownerDrawElement: anNMLVCUSTOMDRAW
(...some condition...) ifTrue:
[| font |
font := anNMLVCUSTOMDRAW font.
font := Font name: font name pointSize: font pointSize.
font beBold.
anNMLVCUSTOMDRAW font: font].

which does work, and the resource leak has gone away, but it seems clumsy
somehow...

So, how should I do this ? And does the font handling actually have a bug in
this area ?

TIA

-- chris
 
 
 

GDI resource leak in "custom draw" font handling ?

Post by Blair McGl » Thu, 12 Feb 2004 02:50:55

Chris Uppal" < XXXX@XXXXX.COM > wrote in message
news:40289a30$0$30865$ XXXX@XXXXX.COM ...
not
here are
leak.

Well spotted Chris.

changes a
far
think
font

Yes. There is a general issue with freeing an un-owned object which is then
re-realised, either directly by sending it #free and then using it in some
way that causes it to be lazily re-realized, or indirectly by changing an
attribute (such as the weight of a Font, or the style of a Pen) that causes
Dolphin to free it for it to be re-realised with the new attribute. The
re-realised object still thinks it is unbowed, and so leaks when it is GC'd.

I have attached a hot fix for this. Essentially what the patch does is to
mark any GDI object which Dolphin creates as owned, whether the on first or
subsequent realisations. Some untidiness is then needed to handle stock
objects (which are never owned). We may refactor this a bit for the actual
5.1.4 patch, but this hotfix does at least plug the leak.

Regards

Blair

--------------------

"#1493"

!GraphicsTool methodsFor!

ownedHandle: aHandle
"Private - Set the handle of the external graphics's tool object
represented and owned by
the receiver to be the argument."

self handle: aHandle.
ownsHandle := true.
self beFinalizable!

basicRealize
"Private - Realize (create) the external resource associated with the
receiver, sent from
the public method, #realize, if not already realized."

self ownedHandle: self createHandle!

realize
"Realize (create) the external resource associated with the receiver, but
only if not
already realized."

^self isRealized ifFalse: [self basicRealize]! !
!GraphicsTool categoriesFor: #ownedHandle:!accessing!private! !
!GraphicsTool categoriesFor: #basicRealize!private!realizing/unrealizing! !
!GraphicsTool categoriesFor: #realize!public!realizing/unrealizing! !

!GraphicsTool class methodsFor!

fromOwnedHandle: aHandle
"Answers an instance of the receiver with aHandle. The handle is owned by
the instance and
will therefore be freed by it."

^(self new)
ownedHandle: aHandle;
yourself! !
!GraphicsTool class categoriesFor: #fromOwnedHandle:!instance
creation!public! !

!StockBrush methodsFor!

ownedHandle: aHandle
"Private - Set the handle of the external graphics's tool object
represented and owned by
the receiver to be the argument."

"Implementation Note: Stock objects should never be free'd"

self handle: aHandle! !
!StockBrush categoriesFor: #ownedHandle:!accessing!private! !

!StockFont methodsFor!

ownedHandle: aHandle
"Private - Set the handle of the external graphics's tool object
represented and owned by
the receiver to be the argument."

"Implementation Note: Stock objects should never be free'd"

self handle: aHandle! !
!StockFont categoriesFor: #ownedHandle:!accessing!private! !

!StockPen methodsFor!

ownedHandle: aHandle
"Private - Set the handle of the external graphics's tool object
represented and owned by
the receiver to be the argument."

"Implementation Note: Stock objects should never be free'd"

self handle: aHandle! !
!StockPen categoriesFor: #ownedHandle:!accessing!private! !




 
 
 

GDI resource leak in "custom draw" font handling ?

Post by Chris Uppa » Fri, 13 Feb 2004 00:54:23

Blair,


Great. Thank you very much. It works a treat.

-- chris