Dear wxPython devs and users.
We have a fairly large multithreaded wxPython application. For thread safety we primarily use the style demonstrated in the bottom of http://wiki.wxpython.org/LongRunningTasks (“Easiest implementation EVER”), i.e. we read out relevant data from the GUI in the main thread before starting a new thread, and the new thread updates the GUI using wx.CallAfter. Every now and then however we run into bugs where we by mistake access or manipulate the GUI from a thread other than the main thread (e.g. forget to use wx.CallAfter). The problem with these bugs is that the code often works, 95-99% of the time nothing bad happens, but then every now and then you get a nasty segfault. This means that the bugs can live for a long time in the code before the are identified, and they are then difficult to reproduce.
What I’m wondering is if there is a way to run or build wxPython so that the program always fails when the GUI is accessed from the wrong thread? i.e some kind of hardened or secure mode. Even if this mode would result in a much slower application it would be really useful for debugging. If not, do you have any other suggestions of how we can weed out such bugs efficiently?
Regards
Daniel Forchheimer
That's a very interesting idea, but I'm afraid it would be a lot of
work, and it would be work at the C++ wxWidgets level. There's no good
general rule for knowing when an API is safe. Each operation would have
to make that determination on its own, and there are a LOT of wxWidgets
entry points to consider.
For example, many wx APIs end up sending a message to the control and
waiting for a response. That kind of operation is safe from a secondary
thread, because the message handling will always be done in the GUI
thread. It's only when you're accessing some shared state that things
get wonky.
Still, it might be worth filing a bug report about this. Maybe it will
pique somebody's interest.
···
daniel.forchheimer@gmail.com wrote:
What I'm wondering is if there is a way to run or build wxPython so
that the program always fails when the GUI is accessed from the wrong
thread? i.e some kind of hardened or secure mode. Even if this mode
would result in a much slower application it would be really useful
for debugging. If not, do you have any other suggestions of how we can
weed out such bugs efficiently?
--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.
In the meantime, maybe you can use code structure and some automated
code review process:
Have all the code that runs in threads clearly separated out into
their own modules. In those modules, do:
from wx import CallAfter
Then you won't be able to accidentally make any other Wx calls. And a
simple grep can assure that that is the only import line in all the
thread code.
It's a good habit to have the real worker code separate from the GUI
code anyway.
-Chris
···
Sent from my iPhone
On Aug 11, 2015, at 9:55 AM, Tim Roberts <timr@probo.com> wrote:
daniel.forchheimer@gmail.com wrote:
What I'm wondering is if there is a way to run or build wxPython so
that the program always fails when the GUI is accessed from the wrong
thread? i.e some kind of hardened or secure mode. Even if this mode
would result in a much slower application it would be really useful
for debugging. If not, do you have any other suggestions of how we can
weed out such bugs efficiently?
That's a very interesting idea, but I'm afraid it would be a lot of
work, and it would be work at the C++ wxWidgets level. There's no good
general rule for knowing when an API is safe. Each operation would have
to make that determination on its own, and there are a LOT of wxWidgets
entry points to consider.
For example, many wx APIs end up sending a message to the control and
waiting for a response. That kind of operation is safe from a secondary
thread, because the message handling will always be done in the GUI
thread. It's only when you're accessing some shared state that things
get wonky.
Still, it might be worth filing a bug report about this. Maybe it will
pique somebody's interest.
--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.
--
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Tim Roberts wrote:
What I'm wondering is if there is a way to run or build wxPython so
that the program always fails when the GUI is accessed from the wrong
thread?
That's a very interesting idea, but I'm afraid it would be a lot of
work, and it would be work at the C++ wxWidgets level. There's no good
general rule for knowing when an API is safe.
It occurred to me later in the day that this really is impossible in the
general case. Most writers think about their main thread as the
exclusive handler for the GUI, but that's just an accident. One subtle
point that many authors miss is that window messages are not delivered
to a process or to a window -- they are delivered to a thread. Each
window belongs to the thread where it was created, and messages for that
window are delivered to the queue in its owning thread. It is perfectly
valid to have 5 threads owning windows, each running a message loop,
each one handling window messages. That's how you can bring up a
message box in a secondary thread -- it gets its own message queue and
runs its own message loop.
···
daniel.forchheimer@gmail.com wrote:
--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.
Would rapping any function, found through grep “thread.start_new_thread(…)” with a decorator using threading.Lock().aquire()/release() around the said function help?
Would rapping any function, found through grep “thread.start_new_thread(…)” with a decorator using threading.Lock().aquire()/release() around the said function help?
This is what I would do, remember the main thread ID somewhere global
and use the wrapper to assert that all handlers are on running on the main thread.
Of course you also need a wrapper to catch exceptions and log the problems or the asserts will be silent.
pysvn workbench has an example of use wrapper to trap and log exceptions.
Barry
···
On 13 Aug 2015, at 20:05, Dev Player devplayer@gmail.com wrote:
–
You received this message because you are subscribed to the Google Groups “wxPython-users” group.
To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.