resource leak in agw.aui.AuiManager

I’m having a memory leakage problem using agw.aui.AuiManager.

I’ve created a stripped down sample that shows the leak - listed below.
I’m creating a panel and destroying it repeatedly. Memory usage grows and after a short while the application fires he following assertion error:

wx._core.PyAssertionError: C++ assertion “IsOk()” failed at …\src\common\image.cpp(1506) in wxIm
age::Replace(): invalid image

I’m calling UnInit() to release the aui manager as described in the doc.

When removing the creation the AuiManager (and the UnInit() ) there is no leakage.

I’m using wx ver:2.9.3.1, but I’m suspecting it happens in ver 2.8.1 as well.

I would appreciate any thought on this.

Thanks,
Oren

import wx
from wx.lib.agw import aui

class MyPanel(wx.Panel):
def init(self, parent):
wx.Panel.init(self, parent)
self._aui_mgr = aui.AuiManager()

def Destroy(self):
    self._aui_mgr.UnInit()
    wx.Panel.Destroy(self)

class MainWindow(wx.Frame):
def init(self):
wx.Frame.init(self, parent=None)
self.Show(True)

    self.Bind(wx.EVT_TIMER, self._on_timer)
    self._timer = wx.Timer(self)
    self._timer.Start(100)

def _on_timer(self, event):
    new_panel = MyPanel(self)
    new_panel.Destroy()

def main():
app = wx.App()
mw = MainWindow()
app.MainLoop()

if name == ‘main’:
main()

What happens if you add a self._aui_mgr.Destroy() after the UnInit?

···

On 3/6/12 6:11 AM, Oren Gampel wrote:

I'm having a memory leakage problem using agw.aui.AuiManager.

I've created a stripped down sample that shows the leak - listed below.
I'm creating a panel and destroying it repeatedly. Memory usage grows
and after a short while the application fires he following assertion error:
wx._core.PyAssertionError: C++ assertion "IsOk()" failed at
..\..\src\common\image.cpp(1506) in wxIm
age::Replace(): invalid image

I'm calling UnInit() to release the aui manager as described in the doc.

When removing the creation the AuiManager (and the UnInit() ) there is
no leakage.

I'm using wx ver:2.9.3.1, but I'm suspecting it happens in ver 2.8.1 as
well.

I would appreciate any thought on this.

--
Robin Dunn
Software Craftsman

This works for me here on Windows 7, wxPython 2.9.3. However, it seems
a bit odd: why do we have to explicitly Destroy() a wx.EvtHandler
(which is what AuiManager is)? And, more important, should I put that
line in the UnInit method of AuiManager directly in the SVN version?

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/

···

On 6 March 2012 19:29, Robin Dunn wrote:

On 3/6/12 6:11 AM, Oren Gampel wrote:

I'm having a memory leakage problem using agw.aui.AuiManager.

I've created a stripped down sample that shows the leak - listed below.
I'm creating a panel and destroying it repeatedly. Memory usage grows
and after a short while the application fires he following assertion
error:
wx._core.PyAssertionError: C++ assertion "IsOk()" failed at
..\..\src\common\image.cpp(1506) in wxIm
age::Replace(): invalid image

I'm calling UnInit() to release the aui manager as described in the doc.

When removing the creation the AuiManager (and the UnInit() ) there is
no leakage.

I'm using wx ver:2.9.3.1, but I'm suspecting it happens in ver 2.8.1 as
well.

I would appreciate any thought on this.

What happens if you add a self._aui_mgr.Destroy() after the UnInit?

I'm having a memory leakage problem using agw.aui.AuiManager.

I've created a stripped down sample that shows the leak - listed below.
I'm creating a panel and destroying it repeatedly. Memory usage grows
and after a short while the application fires he following assertion
error:
wx._core.PyAssertionError: C++ assertion "IsOk()" failed at
..\..\src\common\image.cpp(1506) in wxIm
age::Replace(): invalid image

I'm calling UnInit() to release the aui manager as described in the doc.

When removing the creation the AuiManager (and the UnInit() ) there is
no leakage.

I'm using wx ver:2.9.3.1, but I'm suspecting it happens in ver 2.8.1 as
well.

I would appreciate any thought on this.

What happens if you add a self._aui_mgr.Destroy() after the UnInit?

This works for me here on Windows 7, wxPython 2.9.3. However, it seems
a bit odd: why do we have to explicitly Destroy() a wx.EvtHandler
(which is what AuiManager is)?

Think of it as if it was a wx.Window with no parent. Normally a wx.Window is destroyed by the parent when the parent is destroyed, (unless you want to do it yourself before that point in time so you call Destroy to get rid of it). And normally top-level windows will destroy themselves when they are closed and that also destroys all the children recursively.

Now if it was possible for a wx.Window to have no parent then there would be nothing that "owns" it on the C++ side that will automatically destroy it when the owner is done with it. Theoretically we could have the Python proxy own the C++ object so it will automatically be destroyed when the proxy object is destroyed, however just like wx.Window the wx.EvtHandler C++ object holds an extra reference to the Python proxy object for use with OOR and event dispatching. So in other words there is a Python reference cycle that can't be broken by the GC, only by causing the C++ object to delete itself which is what Destroy() does.

Another way to look at it is that this is simply the same pattern used by wx.Dialogs, wx.TaskbarIcons and menus used with PopupMenu. You need to explicitly destroy them when done with them.

And, more important, should I put that
line in the UnInit method of AuiManager directly in the SVN version?

If it is fairly certain that nothing else will be done with the AuiManager after UnInit is called then it should be safe to have it destroy itself there.

···

On 3/6/12 11:43 AM, Andrea Gavana wrote:

On 6 March 2012 19:29, Robin Dunn wrote:

On 3/6/12 6:11 AM, Oren Gampel wrote:

--
Robin Dunn
Software Craftsman

Thanks a lot for you responses!

The original problem rises on win XP and also Linux (checked Ubuntu and Kubuntu) in version 2.9. and 2.8.

Adding the suggested self._aui_mgr.Destroy() does resolve the problem and the test program stops leaking.

However, while creating the stripped down version, I’ve omitted the call

    self._aui_mgr.SetManagedWindow(self)

after creating the aui manager. When this is set I can no longer Destroy() the manager, but there is also no leak. I’ve now added UnInint() to the Destroy of all my AuiManger() and Indeed most of the leaks are gone.

However:

Andrea, please note that AuiNotebook Doesn’t UnInit()

The following code shows my current leak. I use the notebook’s GetAuiManager() and UnInit() it myself. This works well, unless I add a page. In this case there is a leak, even if I explicitly DeletePage() it.

Again, thank you for your input!

class MyNotebook(aui.AuiNotebook):
def init(self, p):
aui.AuiNotebook.init(self, p, -1)
self._page = wx.Panel(self, -1)
self.AddPage(self._page, ‘?’)

def Destroy(self):
    found, idx = self.FindTab(self._page)
    if found:
        self.DeletePage(idx)

    self.GetAuiManager().UnInit() #workaround the missing UnInit()
    aui.AuiNotebook.Destroy(self)

class MainWindow(wx.Frame):
def init(self):
wx.Frame.init(self, parent=None)
self.Show(True)

    self.Bind(wx.EVT_TIMER, self._on_timer)
    self._timer = wx.Timer(self)
    self._timer.Start(100)

def _on_timer(self, event):
    new_panel = MyNotebook(self)
    new_panel.Destroy()

def main():
app = wx.App()
mw = MainWindow()
app.MainLoop()

if name == ‘main’:
main()

···

On Tuesday, March 6, 2012 4:11:52 PM UTC+2, Oren wrote:

I’m having a memory leakage problem using agw.aui.AuiManager.

I’ve created a stripped down sample that shows the leak - listed below.
I’m creating a panel and destroying it repeatedly. Memory usage grows and after a short while the application fires he following assertion error:

wx._core.PyAssertionError: C++ assertion “IsOk()” failed at …..\src\common\image.cpp(1506) in wxIm
age::Replace(): invalid image

I’m calling UnInit() to release the aui manager as described in the doc.

When removing the creation the AuiManager (and the UnInit() ) there is no leakage.

I’m using wx ver:2.9.3.1, but I’m suspecting it happens in ver 2.8.1 as well.

I would appreciate any thought on this.

Thanks,
Oren

import wx
from wx.lib.agw import aui

class MyPanel(wx.Panel):
def init(self, parent):
wx.Panel.init(self, parent)
self._aui_mgr = aui.AuiManager()

def Destroy(self):
    self._aui_mgr.UnInit()
    wx.Panel.Destroy(self)

class MainWindow(wx.Frame):
def init(self):
wx.Frame.init(self, parent=None)
self.Show(True)

    self.Bind(wx.EVT_TIMER, self._on_timer)
    self._timer = wx.Timer(self)
    self._timer.Start(100)

def _on_timer(self, event):
    new_panel = MyPanel(self)
    new_panel.Destroy()

def main():
app = wx.App()
mw = MainWindow()
app.MainLoop()

if name == ‘main’:
main()

On Tuesday, March 6, 2012 4:11:52 PM UTC+2, Oren wrote:

I’m having a memory leakage problem using agw.aui.AuiManager.

I’ve created a stripped down sample that shows the leak - listed below.
I’m creating a panel and destroying it repeatedly. Memory usage grows and after a short while the application fires he following assertion error:

wx._core.PyAssertionError: C++ assertion “IsOk()” failed at …..\src\common\image.cpp(1506) in wxIm
age::Replace(): invalid image

I’m calling UnInit() to release the aui manager as described in the doc.

When removing the creation the AuiManager (and the UnInit() ) there is no leakage.

I’m using wx ver:2.9.3.1, but I’m suspecting it happens in ver 2.8.1 as well.

I would appreciate any thought on this.

Thanks,
Oren

import wx
from wx.lib.agw import aui

class MyPanel(wx.Panel):
def init(self, parent):
wx.Panel.init(self, parent)
self._aui_mgr = aui.AuiManager()

def Destroy(self):
    self._aui_mgr.UnInit()
    wx.Panel.Destroy(self)

class MainWindow(wx.Frame):
def init(self):
wx.Frame.init(self, parent=None)
self.Show(True)

    self.Bind(wx.EVT_TIMER, self._on_timer)
    self._timer = wx.Timer(self)
    self._timer.Start(100)

def _on_timer(self, event):
    new_panel = MyPanel(self)
    new_panel.Destroy()

def main():
app = wx.App()
mw = MainWindow()
app.MainLoop()

if name == ‘main’:
main()

On Tuesday, March 6, 2012 4:11:52 PM UTC+2, Oren wrote:

I’m having a memory leakage problem using agw.aui.AuiManager.

I’ve created a stripped down sample that shows the leak - listed below.
I’m creating a panel and destroying it repeatedly. Memory usage grows and after a short while the application fires he following assertion error:

wx._core.PyAssertionError: C++ assertion “IsOk()” failed at …..\src\common\image.cpp(1506) in wxIm
age::Replace(): invalid image

I’m calling UnInit() to release the aui manager as described in the doc.

When removing the creation the AuiManager (and the UnInit() ) there is no leakage.

I’m using wx ver:2.9.3.1, but I’m suspecting it happens in ver 2.8.1 as well.

I would appreciate any thought on this.

Thanks,
Oren

import wx
from wx.lib.agw import aui

class MyPanel(wx.Panel):
def init(self, parent):
wx.Panel.init(self, parent)
self._aui_mgr = aui.AuiManager()

def Destroy(self):
    self._aui_mgr.UnInit()
    wx.Panel.Destroy(self)

class MainWindow(wx.Frame):
def init(self):
wx.Frame.init(self, parent=None)
self.Show(True)

    self.Bind(wx.EVT_TIMER, self._on_timer)
    self._timer = wx.Timer(self)
    self._timer.Start(100)

def _on_timer(self, event):
    new_panel = MyPanel(self)
    new_panel.Destroy()

def main():
app = wx.App()
mw = MainWindow()
app.MainLoop()

if name == ‘main’:
main()

On Tuesday, March 6, 2012 4:11:52 PM UTC+2, Oren wrote:

I’m having a memory leakage problem using agw.aui.AuiManager.

I’ve created a stripped down sample that shows the leak - listed below.
I’m creating a panel and destroying it repeatedly. Memory usage grows and after a short while the application fires he following assertion error:

wx._core.PyAssertionError: C++ assertion “IsOk()” failed at …..\src\common\image.cpp(1506) in wxIm
age::Replace(): invalid image

I’m calling UnInit() to release the aui manager as described in the doc.

When removing the creation the AuiManager (and the UnInit() ) there is no leakage.

I’m using wx ver:2.9.3.1, but I’m suspecting it happens in ver 2.8.1 as well.

I would appreciate any thought on this.

Thanks,
Oren

import wx
from wx.lib.agw import aui

class MyPanel(wx.Panel):
def init(self, parent):
wx.Panel.init(self, parent)
self._aui_mgr = aui.AuiManager()

def Destroy(self):
    self._aui_mgr.UnInit()
    wx.Panel.Destroy(self)

class MainWindow(wx.Frame):
def init(self):
wx.Frame.init(self, parent=None)
self.Show(True)

    self.Bind(wx.EVT_TIMER, self._on_timer)
    self._timer = wx.Timer(self)
    self._timer.Start(100)

def _on_timer(self, event):
    new_panel = MyPanel(self)
    new_panel.Destroy()

def main():
app = wx.App()
mw = MainWindow()
app.MainLoop()

if name == ‘main’:
main()

On Tuesday, March 6, 2012 4:11:52 PM UTC+2, Oren wrote:

I’m having a memory leakage problem using agw.aui.AuiManager.

I’ve created a stripped down sample that shows the leak - listed below.
I’m creating a panel and destroying it repeatedly. Memory usage grows and after a short while the application fires he following assertion error:

wx._core.PyAssertionError: C++ assertion “IsOk()” failed at …..\src\common\image.cpp(1506) in wxIm
age::Replace(): invalid image

I’m calling UnInit() to release the aui manager as described in the doc.

When removing the creation the AuiManager (and the UnInit() ) there is no leakage.

I’m using wx ver:2.9.3.1, but I’m suspecting it happens in ver 2.8.1 as well.

I would appreciate any thought on this.

Thanks,
Oren

import wx
from wx.lib.agw import aui

class MyPanel(wx.Panel):
def init(self, parent):
wx.Panel.init(self, parent)
self._aui_mgr = aui.AuiManager()

def Destroy(self):
    self._aui_mgr.UnInit()
    wx.Panel.Destroy(self)

class MainWindow(wx.Frame):
def init(self):
wx.Frame.init(self, parent=None)
self.Show(True)

    self.Bind(wx.EVT_TIMER, self._on_timer)
    self._timer = wx.Timer(self)
    self._timer.Start(100)

def _on_timer(self, event):
    new_panel = MyPanel(self)
    new_panel.Destroy()

def main():
app = wx.App()
mw = MainWindow()
app.MainLoop()

if name == ‘main’:
main()

On Tuesday, March 6, 2012 4:11:52 PM UTC+2, Oren wrote:

I’m having a memory leakage problem using agw.aui.AuiManager.

I’ve created a stripped down sample that shows the leak - listed below.
I’m creating a panel and destroying it repeatedly. Memory usage grows and after a short while the application fires he following assertion error:

wx._core.PyAssertionError: C++ assertion “IsOk()” failed at …..\src\common\image.cpp(1506) in wxIm
age::Replace(): invalid image

I’m calling UnInit() to release the aui manager as described in the doc.

When removing the creation the AuiManager (and the UnInit() ) there is no leakage.

I’m using wx ver:2.9.3.1, but I’m suspecting it happens in ver 2.8.1 as well.

I would appreciate any thought on this.

Thanks,
Oren

import wx
from wx.lib.agw import aui

class MyPanel(wx.Panel):
def init(self, parent):
wx.Panel.init(self, parent)
self._aui_mgr = aui.AuiManager()

def Destroy(self):
    self._aui_mgr.UnInit()
    wx.Panel.Destroy(self)

class MainWindow(wx.Frame):
def init(self):
wx.Frame.init(self, parent=None)
self.Show(True)

    self.Bind(wx.EVT_TIMER, self._on_timer)
    self._timer = wx.Timer(self)
    self._timer.Start(100)

def _on_timer(self, event):
    new_panel = MyPanel(self)
    new_panel.Destroy()

def main():
app = wx.App()
mw = MainWindow()
app.MainLoop()

if name == ‘main’:
main()

On Tuesday, March 6, 2012 4:11:52 PM UTC+2, Oren wrote:

I’m having a memory leakage problem using agw.aui.AuiManager.

I’ve created a stripped down sample that shows the leak - listed below.
I’m creating a panel and destroying it repeatedly. Memory usage grows and after a short while the application fires he following assertion error:

wx._core.PyAssertionError: C++ assertion “IsOk()” failed at …..\src\common\image.cpp(1506) in wxIm
age::Replace(): invalid image

I’m calling UnInit() to release the aui manager as described in the doc.

When removing the creation the AuiManager (and the UnInit() ) there is no leakage.

I’m using wx ver:2.9.3.1, but I’m suspecting it happens in ver 2.8.1 as well.

I would appreciate any thought on this.

Thanks,
Oren

import wx
from wx.lib.agw import aui

class MyPanel(wx.Panel):
def init(self, parent):
wx.Panel.init(self, parent)
self._aui_mgr = aui.AuiManager()

def Destroy(self):
    self._aui_mgr.UnInit()
    wx.Panel.Destroy(self)

class MainWindow(wx.Frame):
def init(self):
wx.Frame.init(self, parent=None)
self.Show(True)

    self.Bind(wx.EVT_TIMER, self._on_timer)
    self._timer = wx.Timer(self)
    self._timer.Start(100)

def _on_timer(self, event):
    new_panel = MyPanel(self)
    new_panel.Destroy()

def main():
app = wx.App()
mw = MainWindow()
app.MainLoop()

if name == ‘main’:
main()

Thanks a lot for you responses!

The original problem rises on win XP and also Linux (checked Ubuntu and
Kubuntu) in version 2.9. and 2.8.

Adding the suggested self._aui_mgr.Destroy() does resolve the problem and
the test program stops leaking.

However, while creating the stripped down version, I've omitted the call

    self\.\_aui\_mgr\.SetManagedWindow\(self\)

after creating the aui manager. When this is set I can no longer Destroy()
the manager, but there is also no leak. I've now added UnInint() to the
Destroy of all my AuiManger() and Indeed most of the leaks are gone.

OK then, I'll modify the source code for framemanager.py in the UnInit
method: if there is not a managed window, I simply call "Destroy()" on
the manager itself.

However:

Andrea, please note that AuiNotebook Doesn't UnInit()

I'll override the Destroy() method for AuiNotebook to take care of this.

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/

···

On 7 March 2012 14:17, Oren wrote:

Robin,

I'm having a memory leakage problem using agw.aui.AuiManager.

I've created a stripped down sample that shows the leak - listed below.
I'm creating a panel and destroying it repeatedly. Memory usage grows
and after a short while the application fires he following assertion
error:
wx._core.PyAssertionError: C++ assertion "IsOk()" failed at
..\..\src\common\image.cpp(1506) in wxIm
age::Replace(): invalid image

I'm calling UnInit() to release the aui manager as described in the doc.

When removing the creation the AuiManager (and the UnInit() ) there is
no leakage.

I'm using wx ver:2.9.3.1, but I'm suspecting it happens in ver 2.8.1 as
well.

I would appreciate any thought on this.

What happens if you add a self._aui_mgr.Destroy() after the UnInit?

This works for me here on Windows 7, wxPython 2.9.3. However, it seems
a bit odd: why do we have to explicitly Destroy() a wx.EvtHandler
(which is what AuiManager is)?

Think of it as if it was a wx.Window with no parent. Normally a wx.Window
is destroyed by the parent when the parent is destroyed, (unless you want to
do it yourself before that point in time so you call Destroy to get rid of
it). And normally top-level windows will destroy themselves when they are
closed and that also destroys all the children recursively.

Now if it was possible for a wx.Window to have no parent then there would be
nothing that "owns" it on the C++ side that will automatically destroy it
when the owner is done with it. Theoretically we could have the Python
proxy own the C++ object so it will automatically be destroyed when the
proxy object is destroyed, however just like wx.Window the wx.EvtHandler C++
object holds an extra reference to the Python proxy object for use with OOR
and event dispatching. So in other words there is a Python reference cycle
that can't be broken by the GC, only by causing the C++ object to delete
itself which is what Destroy() does.

Another way to look at it is that this is simply the same pattern used by
wx.Dialogs, wx.TaskbarIcons and menus used with PopupMenu. You need to
explicitly destroy them when done with them.

Thank you for the explanation, it's much clearer right now. I
erroneously thought that wx.EvtHandler, not being a "real" widget,
didn't need to be explicitly destroyed.

And, more important, should I put that
line in the UnInit method of AuiManager directly in the SVN version?

If it is fairly certain that nothing else will be done with the AuiManager
after UnInit is called then it should be safe to have it destroy itself
there.

Done in the latest SVN.

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/

···

On 7 March 2012 00:08, Robin Dunn wrote:

On 3/6/12 11:43 AM, Andrea Gavana wrote:

On 6 March 2012 19:29, Robin Dunn wrote:

On 3/6/12 6:11 AM, Oren Gampel wrote:

Thanks a lot for the quick fix!

Can you please confirm the leak I mentioned earlier?

The following code shows my current leak. I use the notebook’s GetAuiManager() and UnInit() it myself. There is no leak, unless I add a page. In this case there is a leak, even if I explicitly DeletePage() it.

I’m using the GetAuiManager() of the notebook to UnInit() it myself.

Again, thank you for your input!

class MyNotebook(aui.AuiNotebook):

def __init__(self, p):
    aui.AuiNotebook.__init__(self, p, -1)

    self._page = wx.Panel(self, -1)
    self.AddPage(self._page, '?')

def Destroy(self):
    found, idx = self.FindTab(self._page)

    if found:
        self.DeletePage(idx)

    self.GetAuiManager().UnInit() #workaround the missing UnInit()
    aui.AuiNotebook.Destroy(self)

class MainWindow(wx.Frame):
def init(self):

    wx.Frame.__init__(self, parent=None)
    self.Show(True)

    self.Bind(wx.EVT_TIMER, self._on_timer)
    self._timer = wx.Timer(self)

    self._timer.Start(100)

def _on_timer(self, event):

    new_panel = MyNotebook(self)
    new_panel.Destroy()

def main():
app = wx.App()

mw = MainWindow()
app.MainLoop()

if name == ‘main’:
main()

···

On Wed, Mar 7, 2012 at 9:50 PM, Andrea Gavana andrea.gavana@gmail.com wrote:

Robin,

On 7 March 2012 00:08, Robin Dunn wrote:

On 3/6/12 11:43 AM, Andrea Gavana wrote:

On 6 March 2012 19:29, Robin Dunn wrote:

On 3/6/12 6:11 AM, Oren Gampel wrote:

I’m having a memory leakage problem using agw.aui.AuiManager.

I’ve created a stripped down sample that shows the leak - listed below.

I’m creating a panel and destroying it repeatedly. Memory usage grows

and after a short while the application fires he following assertion

error:

wx._core.PyAssertionError: C++ assertion “IsOk()” failed at

…..\src\common\image.cpp(1506) in wxIm

age::Replace(): invalid image

I’m calling UnInit() to release the aui manager as described in the doc.

When removing the creation the AuiManager (and the UnInit() ) there is

no leakage.

I’m using wx ver:2.9.3.1, but I’m suspecting it happens in ver 2.8.1 as

well.

I would appreciate any thought on this.

What happens if you add a self._aui_mgr.Destroy() after the UnInit?

This works for me here on Windows 7, wxPython 2.9.3. However, it seems

a bit odd: why do we have to explicitly Destroy() a wx.EvtHandler

(which is what AuiManager is)?

Think of it as if it was a wx.Window with no parent. Normally a wx.Window

is destroyed by the parent when the parent is destroyed, (unless you want to

do it yourself before that point in time so you call Destroy to get rid of

it). And normally top-level windows will destroy themselves when they are

closed and that also destroys all the children recursively.

Now if it was possible for a wx.Window to have no parent then there would be

nothing that “owns” it on the C++ side that will automatically destroy it

when the owner is done with it. Theoretically we could have the Python

proxy own the C++ object so it will automatically be destroyed when the

proxy object is destroyed, however just like wx.Window the wx.EvtHandler C++

object holds an extra reference to the Python proxy object for use with OOR

and event dispatching. So in other words there is a Python reference cycle

that can’t be broken by the GC, only by causing the C++ object to delete

itself which is what Destroy() does.

Another way to look at it is that this is simply the same pattern used by

wx.Dialogs, wx.TaskbarIcons and menus used with PopupMenu. You need to

explicitly destroy them when done with them.

Thank you for the explanation, it’s much clearer right now. I

erroneously thought that wx.EvtHandler, not being a “real” widget,

didn’t need to be explicitly destroyed.

And, more important, should I put that

line in the UnInit method of AuiManager directly in the SVN version?

If it is fairly certain that nothing else will be done with the AuiManager

after UnInit is called then it should be safe to have it destroy itself

there.

Done in the latest SVN.

Andrea.

“Imagination Is The Only Weapon In The War Against Reality.”

http://xoomer.alice.it/infinity77/

To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com

or visit http://groups.google.com/group/wxPython-users?hl=en

Hi,

Thanks a lot for the quick fix!

Can you please confirm the leak I mentioned earlier?

The following code shows my current leak. I use the notebook's
GetAuiManager() and UnInit() it myself. There is no leak, *unless I add a
page*. In this case there is a leak, even if I explicitly DeletePage() it.

I'm using the GetAuiManager() of the notebook to UnInit() it myself.

There shouldn't be any need for this if you are using the SVN version
of AGW. If you're not, please upgrade your current AGW version.

class MyNotebook(aui.AuiNotebook):
def __init__(self, p):
aui.AuiNotebook.__init__(self, p, -1)
self._page = wx.Panel(self, -1)
self.AddPage(self._page, '?')

def Destroy\(self\):
    found, idx = self\.FindTab\(self\.\_page\)
    if found:
        self\.DeletePage\(idx\)

    self\.GetAuiManager\(\)\.UnInit\(\) \#workaround the missing UnInit\(\)
    aui\.AuiNotebook\.Destroy\(self\)

class MainWindow(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, parent=None)
self.Show(True)

    self\.Bind\(wx\.EVT\_TIMER, self\.\_on\_timer\)
    self\.\_timer = wx\.Timer\(self\)
    self\.\_timer\.Start\(100\)

def \_on\_timer\(self, event\):
    new\_panel = MyNotebook\(self\)

    new\_panel\.Destroy\(\)

def main():
app = wx.App()
mw = MainWindow()
app.MainLoop()

if __name__ == '__main__':
main()

Your sample (!) app almost took my WIndows 7 machine to hell. I don't
know what the problem is, but I wonder what are you trying to do by
creating and destroying an AUI-based layout a gazillion of times. Now,
if you are able to give me a plausible reason for this woodoo-code,
I'll take a look at what the problem might be. Otherwise, I'll wait
for a patch from you to fix the issue.

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/

···

On 11 March 2012 09:34, Oren Gampel wrote:

Dear Mr. Gavana,

I apologize for taking your win 7 to the brinks of hell, but I promise you that my win XP, Ubuntu and Kubuntu all die gracefully with only wx assertions to escort them on their merry way to code heaven :slight_smile:

My original application uses several notebooks embedded within a notebook (all agw). There are about 10-15 pages in the “top level” notebook, each page is a notebook holding 5 to 20 “low level” pages itself. The application holds more than 200 “low level” pages, or leafs, in a hierarchy that depends on a server state, and I must say that it does it very well! Occasionally, the server state changes which means that the top level notebook changes, possibly loosing some pages and/or gaining new ones with new “low level” pages. So, whenever such a change accrues, there are many pages that are deleted and new ones created. After several times my application’s memory grows and than terminated with nasty assertions from wx.

I admit that this might be considered an extreme use of wx and agw, but my sample is a very simple and stripped from all the above layers of complexity. Without the addition of page to the notebook, the “woodoo-code” runs a gazillion times without any leakage (and successful avoids visiting Hades), but with the addition of a single page (and it’s deletion) the memory visibly grows, and wx crashes in few short minutes on an XP. I believe it’s a “fair” example to show the core leakage source. Of course if I’m doing anything out of order in the code I would love knowing what it is.

Thanks again,
Oren

···

On Sun, Mar 11, 2012 at 9:34 PM, Andrea Gavana andrea.gavana@gmail.com wrote:

Hi,

On 11 March 2012 09:34, Oren Gampel wrote:

Thanks a lot for the quick fix!

Can you please confirm the leak I mentioned earlier?

The following code shows my current leak. I use the notebook’s

GetAuiManager() and UnInit() it myself. There is no leak, *unless I add a

page*. In this case there is a leak, even if I explicitly DeletePage() it.

I’m using the GetAuiManager() of the notebook to UnInit() it myself.

There shouldn’t be any need for this if you are using the SVN version

of AGW. If you’re not, please upgrade your current AGW version.

class MyNotebook(aui.AuiNotebook):

def __init__(self, p):
    aui.AuiNotebook.__init__(self, p, -1)
    self._page = wx.Panel(self, -1)
    self.AddPage(self._page, '?')
def Destroy(self):
    found, idx = self.FindTab(self._page)
    if found:
        self.DeletePage(idx)
    self.GetAuiManager().UnInit() #workaround the missing UnInit()
    aui.AuiNotebook.Destroy(self)

class MainWindow(wx.Frame):

def __init__(self):
    wx.Frame.__init__(self, parent=None)
    self.Show(True)
    self.Bind(wx.EVT_TIMER, self._on_timer)
    self._timer = wx.Timer(self)
    self._timer.Start(100)
def _on_timer(self, event):
    new_panel = MyNotebook(self)
    new_panel.Destroy()

def main():

app = wx.App()
mw = MainWindow()
app.MainLoop()

if name == ‘main’:

main()

Your sample (!) app almost took my WIndows 7 machine to hell. I don’t

know what the problem is, but I wonder what are you trying to do by

creating and destroying an AUI-based layout a gazillion of times. Now,

if you are able to give me a plausible reason for this woodoo-code,

I’ll take a look at what the problem might be. Otherwise, I’ll wait

for a patch from you to fix the issue.

Andrea.

“Imagination Is The Only Weapon In The War Against Reality.”

http://xoomer.alice.it/infinity77/

To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com

or visit http://groups.google.com/group/wxPython-users?hl=en

Good. Not as good as I thought, but you never get what you ask for. I
can't really see what the problem is with the AuiNotebook code itself,
as with the DeletePage the window is correctly destroyed. AddPage
doesn't really do anything special by itself, so I am a bit unsure
what the issue is here.

I have run your code **without the UnInit** line you put in (because I
told you to use the latest SVN version already) for about 3890
iterations of this create/destroy thingy (it's still running) and my
RAM monitor shows an increase of 4MB only from the start of this
"simulation". I didn't get any traceback yet, although at some point I
will get one (eventually).

Now that I got to 7770 iterations, I feel it's about time to go to
bed. Please do let me know when you're ready to contribute a patch to
solve this problem.

Thank you.

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/

···

On 11 March 2012 21:44, Oren Gampel wrote:

Dear Mr. Gavana,

I apologize for taking your win 7 to the brinks of hell, but I promise you
that my win XP, Ubuntu and Kubuntu all die gracefully with only wx
assertions to escort them on their merry way to code heaven :slight_smile:

My original application uses several notebooks embedded within a notebook
(all agw). There are about 10-15 pages in the "top level" notebook, each
page is a notebook holding 5 to 20 "low level" pages itself. The application
holds more than 200 "low level" pages, or leafs, in a hierarchy that depends
on a server state, and I must say that it does it very well! Occasionally,
the server state changes which means that the top level notebook changes,
possibly loosing some pages and/or gaining new ones with new "low level"
pages. So, whenever such a change accrues, there are many pages that are
deleted and new ones created. After several times my application's memory
grows and than terminated with nasty assertions from wx.

I admit that this might be considered an extreme use of wx and agw, but my
sample is a very simple and stripped from all the above layers of
complexity. Without the addition of page to the notebook, the "woodoo-code"
runs a gazillion times without any leakage (and successful avoids visiting
Hades), but with the addition of a single page (and it's deletion) the
memory visibly grows, and wx crashes in few short minutes on an XP. I
believe it's a "fair" example to show the core leakage source. Of course if
I'm doing anything out of order in the code I would love knowing what it is.