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

Reply via email to