[Chandler-dev] How to trap calls to wx methods from non-gui threads

Robin Dunn robin at alldunn.com
Fri Jan 18 14:48:02 PST 2008


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!



More information about the chandler-dev mailing list