#159 PyCWnd.DestroyWindow causes memory access & stack faults

pythonwin (176)

(b203 and all previous builds I know)
win32ui does or causes indirectly something odd with
memory in PyCWnd.DestroyWindow or WM_NCDESTROY handling.

I watch this problem for years with different win32ui
based apps, yet I'm afraid that I cannot manage to
deliver a reproducable minimalistic crashing app,
though I tried. Its a nasty stochastical memory damage
problem I think. I can reproduce the crash here with
different bigger apps in different situations. Now I
have one where I manage to crash it >90% and did 100's
of tests to isolate the problem and track it down. Thus
I found it to be caused (here) by a
PyCWnd.DestroyWindow call, but the actual crash takes
place far later when the operative message handler has
returned to the message loop. Some damage in memory.

Some users maybe know that PythonWin itself sometimes
crashes over the year at the end of some sessions, when
debug windows were open or complex (own) window
situations or randomly. Maybe there is a connection to
the windows destroying & memory problem here.

I'm quite sure there is a unresolved nasty bug in the
DestroyWindow Process or with WM_NCDESTROY handling in
win32ui. (Think is doesn't have to do with bug 906305 -
in ui_window_destroy_window there is no CEnterLeave..
but GUI_BGN_SAVE/END_SAVE which seem to be correct )

I tell what I know about the bug:

- I use win32ui for some GUI based tools since years. I
get occasional crashes on certain window and non-modal
dialog closings in different situations. memory
problems of other code can be excluded. I traced it
down to certain window destroyings going on

- latest crash traces with registers far below
(b203/py2.3.4), yet that will probably not tell much as
there are indirect memory effects

- the example code snipet below is the final handler of
a autocompletion drop-down SysListCtrl32 in
PyCFrameWnd: Upon certain key events the window has to
be destroyed explicitely and after that some simple
computation/and pasting to clipboard occurs - then
return to message loop When
self.aclstbase.DestroyWindow() is really done then in
certain memory constellations the app crashes. Its very
sensitive and abviously random. E.g. when i start the
app and use it to a certain extent, then the bug will
not show for long etc etc.
Yet when alternative
self.aclstbase.PostMessage(WM_CLOSE) is used in that
case, the app crashes never ever in that situation.

- the memory address of access fault changes in
reproducible cases, when more or less python
computations are done after the .DestroyWindow().

- The crash bug is more often on my Win98 than my WinXP
- maybe because there is less memory ....

- In other apps (mainly on my Win98) similar problems
occur, when progress dialogs (non-modal) are destroyed
or certain othe non-modal dialogs with commctrl childs.

-In other apps (mainly on my Win98) a crash when
multiple modal dialogs have the same parent and one is
closed manually.

- I think there are always other complex childs
(window.Wnd hooked) inside the window/dialog that shows
the closing crash. If its a simple plain dialog/window
the bug maybe doesn't show at all (but Im not sure)

- Always when the suspicios .DestroyWindow() or manual
window closing methods call can be replaces by
PostMessage(WM_CLOSE) or PostWM_USER- or
timer-delayed .DestroyWindow() the crash can be
99%..100% (not completely sure) eliminated.
Unfortunately .DestroyWindow() cannot be replaced always.


- Certain things are going on with the invalid CWnd*
after DestroyWindow - Cannot oversee this

- Problem when WM_NCDESTROY is handled.
( not sure if make sens but when I run a certain
bigger app window (lots of childs and toolbars in) and
do on the open mainframe the following
>>> mainframe.SendMessage(wc.WM_DESTROY)
>>> mainframe.SendMessage(wc.WM_NCDESTROY)
...Window focus change to still existing mainframe ->
crash. Think no matter if it makes sense, win32ui
should not raise a seg fault.?)

- Invalide Message Routing / Calling
( the crash is always from win32ui at bottom of the
call stack one or 3 or 2 calls later (randomly going
somewhere into the open memory) )

- ThreadState Problems
(Yet I reproduce the bug in apps with no extra
threads or so going on)

- Py/C AttachObject/Detach Problem
( Yet I played around on CmdTarget._obj_ level. The
problem seems not to be there. )

My debugging knowledge not enough to find out more for
now. I could make suggested tests in the crashing
apps+computers if that helps? The bug is a constant,
rare but unforseable instability problem with many of
my tools.


def AutoCompleteTake(self,sn=None):
#cleanup auto-c window

(b203/py2.3.4 stack traces memory access errors after

MFC42! 73d99c2a()
WIN32UI! 1002a268()

MFC42! 73d99c2a()
WIN32UI! 1002a268()

WIN32UI! 0117f7b8()

MFC42! 73d332fe()
WIN32UI! 0117f7b8()

MFC42! 73d332fb()
WIN32UI! 0117f7b8()

EAX = 00000000 EBX = 007A075A
ECX = 01499FD8 EDX = 00000000
ESI = 0012F4CC EDI = 01499FD8
EIP = 73D332FB ESP = 0012F0C8
EBP = 0012F0F0 EFL = 00000206 CS = 001B
DS = 0023 ES = 0023 SS = 0023 FS = 0038
GS = 0000 OV=0 UP=0 EI=1 PL=0 ZR=0 AC=0
PE=1 CY=0

00000014 = ????????

ST0 = -0.14695186589127226e+1843
ST1 = +0.00000000000000000e+0000
ST2 = +4.30166298621518843e+3581
ST3 = +0.00000000000000000e+0000
ST4 = +0.00000000000000000e+0000
ST5 = +2.10999965667724609e-0001
ST6 = +0.00000000000000000e+0000
ST7 = +0.00000000000000000e+0000
CTRL = 027F STAT = 4020 TAGS = FFFF
EIP = 1E04B200 CS = 001B DS = 0023
EDO = 0012E3E0


  • kxroberto

    • priority: 5 --> 8
  • Ada Linux
    Ada Linux

    Logged In: YES

    WM_NCDESTROY is handled in a funny way by Pythonwin.
    Actually, if I recall correctly, ALL messages are handled
    differently that you would normally expect in a MFC app.

    Messages are not received the usual way, using MFC message
    handlers. Instead a Windows message hook is installed which
    intercepts messages and dispatches them.

    I also had problems because WM_NCDESTORY, but they were of a
    different nature (so I remember). To solve them I removed
    the message hooks (which the Platform SDK says it can
    significantly slow you down) and converted win32ui to use
    normal message dispatching. This was kind of hard and I'm
    not sure I did it 100% correctly.

    If you want, I can make a patch against pywin32 build 203
    for you to try and see if it solves your problem.

  • Mark Hammond
    Mark Hammond

    Logged In: YES

    I'd be interested in a look at the patch.

  • Ada Linux
    Ada Linux

    Logged In: YES

    Since I can't upload the patch here I'll put it into the
    Patches section.

  • kxroberto

    Logged In: YES

    After getting a debug version of win32ui work, I found the
    location of the problem in my case (see below) and a
    temporary patch of win32uiExt.h.
    The Error was in the second location: OnNotify; the change
    in OnCmdMsg is just a analog guess (reasonable?). Maybe
    there are even more Python-callback occasions after which a
    destroyed window causes mem.acces errors.
    My guess: A Pythonic Notification Handler destroys the
    Window itself with .DestroyWindow() [and also the child
    yielding the notification]. Then the CWnd's "this" or the
    window handle or whatever become invalid/unusable and
    T::OnNotify crashes. Yet I have no complete overview why. My
    patch maybe only cures the symptom on a high level.? Maybe
    there are even more Python-callback calls after which a
    destroyed window can cause mem.acces errors?
    Don't know if adalx's hook-less windowproc solution also
    cures the problem. Also dont know if there is still another
    problem with WM_NCDESTROY?

    Yet, so far all my obscure win32ui window handling crashes
    (as described) disapeared and lately maybe I can fullfill my
    statement to a collage: Pythonic MFC apps never crash hard
    but only yield pleasant python exceptions...

    cvs diff win32uiExt.h (in directory
    Index: win32uiExt.h
    RCS file: /cvsroot/pywin32/pywin32/Pythonwin/win32uiExt.h,v
    retrieving revision 1.5
    diff -r1.5 win32uiExt.h
    < else
    > else {
    > if (!IsWindow( this->m_hWnd ))
    > return TRUE;
    > }
    < else
    > else {
    > if (!IsWindow( ((NMHDR*)lParam)->hwndFrom ))
    > return TRUE;
    > }

    *****CVS exited normally with code 1*****

    MSVC6++ Debugger stopped here (2nd function from top of stack):

    virtual BOOL OnNotify (WPARAM wParam, LPARAM lParam,
    LRESULT *pResult) {
    // yield to Python first
    if (Python_OnNotify (this, wParam, lParam, pResult))
    return TRUE;
    ====> return T::OnNotify (wParam, lParam, pResult);

    MFC42! 73d332fb()
    * const 0x00e8ef38 {CPythonWndFramework<CFrameWnd>
    hWnd=0x0082558c}, unsigned int 1943215600, long 777, long *
    0x0012f4cc) line 78 + 10 bytes
    MFC42! 73d31df0()
    MFC42! 73d31cea()
    MFC42! 73d31c73()
    MFC42! 73d31bfb()
    MFC42! 73d31bba()
    USER32! 77d13a50()
    USER32! 77d13b1f()
    USER32! 77d144f5()
    USER32! 77d14525()
    NTDLL! 77f65da3()
    USER32! 77d154b4()
    COMCTL32! 773156f8()
    COMCTL32! 773272ed()
    COMCTL32! 77327406()
    USER32! 77d13a50()
    USER32! 77d13b1f()
    USER32! 77d15b2c()
    USER32! 77d15f73()
    MFC42! 73d320f2()
    MFC42! 73d31d01()
    MFC42! 73d31c73()
    MFC42! 73d31bfb()
    MFC42! 73d31bba()
    USER32! 77d13a50()
    USER32! 77d13b1f()
    USER32! 77d13d79()
    USER32! 77d14374()

  • Mark Hammond
    Mark Hammond

    Logged In: YES


    Checking in pythonpsheet.cpp;
    new revision: 1.3; previous revision: 1.2
    Checking in win32uiExt.h;
    new revision: 1.9; previous revision: 1.8

  • Mark Hammond
    Mark Hammond

    • status: open --> closed-fixed