Hi All,
For diagnosing Bug #11689 I made a temporary hack to wxPython that would
drop control into the debugger if there were any calls to wx functions
or methods from a non-gui thread. Grant asked me how to do this so I
figured I'd send the details to the list in case anybody else wants to know.
Here is a description of what I did for the test. SWIG has a directive
that can be used to specify extra code to wrap around all calls the the
wrapped functions. For wxPython that directive is used in
wxPython/src/_defs.i, near the top of the file you'll see some macros
that use the %exception directive. I added the following line of code
in two of the macros, as the first line after the %exception:
if (! wxThread::IsMain()) wxTrap();
I put it in the %threadWrapperOn macro and the MustHaveApp macro. The
others are used when we don't care about the Python global interpreter
lock, so I used that as an indication of not caring about the GUI thread
either. That turned out to be a good indicator in all but a few cases,
detailed below.
Once this change has been made you can do a clean build of wx, and that
will rerun SWIG and insert that line in a few thousand places in the
generated code. I recommend doing this with a debug build because you
will want to be able to trace up and down stack frames in the debugger
to find out where in the Python code the call is happening.
As I mentioned before, there are a few places where the code above is
used that are legitimate things to do from worker threads. We can
probably come up with a better way to manage them (such as create a new
swig %exception macro and use it on those declarations) but for now I
just tweaked them by hand. Basically this means that you will need to
go into the code generated by SWIG and remove a few of those extra lines
of code. If you don't then the execution will stop in the debugger for
these legitimate cases, and although you can still use the continue
command and keep running, it can get annoying. The files that need
modified are in wxPython/src/[mac|gtk|msw] depending on which platform
you are on. Search for the functions named below and comment out the
line of code with the IsMain test:
_core_wrap.cpp:
_wrap_Event_SetEventType
_wrap_new_PyEvent
_wrap_delete_PyEvent
_wrap_PyEvent__SetSelf
_wrap_PyEvent__GetSelf
_wrap_PostEvent
_wrap_GetApp
_misc_wrap.cpp
_wrap_Thread_IsMain
There are probably a few other places, but these are the ones I ran into.
You can now rebuild wxPython again to pick up those changes.
Now you can run Chander with gdb (or the VisStudio debugger on Windows)
and when some non-gui thread calls one of the functions that still has
the IsMain test in it then the debugger will stop on that line. If you
have the Python gdb macros[1] loaded then you can use the up command to
until you get up to the PyEval_EvalFrameEx frame and then run the
pyframe command to see where in the Python code you are at, and continue
using up and pyframe to see how you got there.
[1] http://svn.python.org/view/*checkout*/python/trunk/Misc/gdbinit
--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Open Source Applications Foundation "chandler-dev" mailing list
http://lists.osafoundation.org/mailman/listinfo/chandler-dev