Threading + ShowModal = Segmentation Fault

Hello,
I have a question on threading with wxPython. I've started a thread
using:
threading.Thread(target=self.RunProgram).start()

From within the thread, I cannot access many things outside of the
class without getting errors. For example, see the following (self is
a class from wx.Panel, the parent is the frame, and sb is a
StatusBar):
self.parent.sb.SetStatusText('Program Running...')

I get the following error (only on Linux, it runs without problems on
Windows):
python: Fatal IO error 0 (Success) on X server :0.0.

I understand that I am not supposed to code it this way and I've found
a solution to this problem by creating a custom event, sending the
event to the panel class that started the thread, and then having a
separate method that updates the status. A bit long winded, but it
works.

However, I can't find a solution to my next problem. I want to create
a modal dialog and have the thread wait for the response of it:
dial = wx.MessageDialog(None, msg, 'Error, Save Current Data?',
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
if dial.ShowModal() == wx.ID_YES:
   do stuff....
else:
   do other stuff...

Again, this works fine under Windows, but linux/GTK gives me a
segmentation fault when ShowModal() is called. I've tried changing
the parent, "None", to be "self" and several other things, but it
would still not work. I can't use the solution I used above, because
I need to get the result of this modal dialog. The thread must not
process anymore until ShowModal returns.

I'm new to programming with threads, can anyone point me in the right
direction? I've tried googling for hours now without any success.

Thanks!

Hi, thanks for your response. I spawn my thread to just run a
function within my panel class, I don't actually create a full class
from threading.Thread. Do I have to do that in your method? And how
can I set an event to a thread, do I just Connect() it as well? Do
you know of any sites with clear examples for doing something similar
to what I'm trying to do - it seems like it would be a pretty common
objective (get input from the user within a thread...), but I haven't
seen any examples.

Thanks,
Scott

···

On Mar 29, 12:27 am, <GadgetSt...@live.co.uk> wrote:

--------------------------------------------------
From: "Scott" <spectre...@gmail.com>
Sent: Monday, March 29, 2010 7:42 AM
To: "wxPython-users" <wxpython-users@googlegroups.com>
Subject: [wxPython-users] Threading + ShowModal = Segmentation Fault

> Hello,
> I have a question on threading with wxPython. I've started a thread
> using:
> threading.Thread(target=self.RunProgram).start()

> From within the thread, I cannot access many things outside of the
> class without getting errors. For example, see the following (self is
> a class from wx.Panel, the parent is the frame, and sb is a
> StatusBar):
> self.parent.sb.SetStatusText('Program Running...')

> I get the following error (only on Linux, it runs without problems on
> Windows):
> python: Fatal IO error 0 (Success) on X server :0.0.

> I understand that I am not supposed to code it this way and I've found
> a solution to this problem by creating a custom event, sending the
> event to the panel class that started the thread, and then having a
> separate method that updates the status. A bit long winded, but it
> works.

> However, I can't find a solution to my next problem. I want to create
> a modal dialog and have the thread wait for the response of it:
> dial = wx.MessageDialog(None, msg, 'Error, Save Current Data?',
> wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
> if dial.ShowModal() == wx.ID_YES:
> do stuff....
> else:
> do other stuff...

> Again, this works fine under Windows, but linux/GTK gives me a
> segmentation fault when ShowModal() is called. I've tried changing
> the parent, "None", to be "self" and several other things, but it
> would still not work. I can't use the solution I used above, because
> I need to get the result of this modal dialog. The thread must not
> process anymore until ShowModal returns.

Hi Scott,
You just need to adapt the approach you used to solve the problem above,
i.e.
1/ When your thread needs to show the modal dialogue raise an event to the
GUI and put your thread into a waiting state, (i.e. set a do nothing flag).
2/ In the GUI show the Dialogue in response to the event.
3/ When the user presses OK or whatever the GUI raises an event on the
thread with the required information.
4/ On the thread receiving this last event it can get the data, (from the
event not the dialogue), and clear the do nothing flag.
As for why it works on windows but not on linux - ideally each thread exists
in its own world completely independent of everything else, in some cases it
might even be on another machine - linux is better at enforcing this than
windows.

> I'm new to programming with threads, can anyone point me in the right
> direction? I've tried googling for hours now without any success.

> Thanks!

> --
> To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
> or visithttp://groups.google.com/group/wxPython-users?hl=en

> To unsubscribe from this group, send email to
> wxpython-users+unsubscribegooglegroups.com or reply to this email with the
> words "REMOVE ME" as the subject.

Hello Scott,

Hello,
I have a question on threading with wxPython. I’ve started a thread
using:
threading.Thread(target=self.RunProgram).start()

From within the thread, I cannot access many things outside of the
class without getting errors. For example, see the following (self is
a class from wx.Panel, the parent is the frame, and sb is a
StatusBar):
self.parent.sb.SetStatusText(‘Program Running…’)

I get the following error (only on Linux, it runs without problems on
Windows):
python: Fatal IO error 0 (Success) on X server :0.0.

I understand that I am not supposed to code it this way and I’ve found
a solution to this problem by creating a custom event, sending the
event to the panel class that started the thread, and then having a
separate method that updates the status. A bit long winded, but it
works.

However, I can’t find a solution to my next problem. I want to create
a modal dialog and have the thread wait for the response of it:
dial = wx.MessageDialog(None, msg, ‘Error, Save Current Data?’,
wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
if dial.ShowModal() == wx.ID_YES:
do stuff…
else:
do other stuff…

Again, this works fine under Windows, but linux/GTK gives me a
segmentation fault when ShowModal() is called. I’ve tried changing
the parent, “None”, to be “self” and several other things, but it
would still not work. I can’t use the solution I used above, because
I need to get the result of this modal dialog. The thread must not
process anymore until ShowModal returns.

I’m new to programming with threads, can anyone point me in the right
direction? I’ve tried googling for hours now without any success.

I don’t have experience with wxPython, so please bear with me.

In c++ wxWidgets when you need to access the GUI library from

a thread, you need to enclose your code inside a

wxMutexGuiEnter() / wxMutexGuiLeave() block.

Seems that it also can be done with wxPython:

http://www.wxpython.org/docs/api/wx-module.html#MutexGuiEnter

HTH

best regards,

Teo Fonrouge

···

On Mar 29, 2010, at 12:42 AM, Scott wrote:

  1. Create a Queue object to send a message back to the child thread from the parent.

  2. Send a custom event to the main loop requesting the dialog, with the queue object embedded in it.

  3. The child thread should now wait until it receives something from the queue, e.g. call queue.get() with no timeout, or combine a timeout and time.sleep in a “while True:” loop.

  4. The main loop shows the dialog, and puts a message into the queue:

if dialog.ShowModal() == wx.ID_YES :

queue.put(True)

There are other ways to do this - in practice, you can just use a variable that both threads can see, as Steve suggested, and as long as you don’t try to modify the GUI from the child thread, this shouldn’t cause problems. However, a queue is the safest way to do it, and a more general solution.

-Nat

···

On Sun, Mar 28, 2010 at 11:42 PM, Scott spectre158@gmail.com wrote:

However, I can’t find a solution to my next problem. I want to create

a modal dialog and have the thread wait for the response of it:

dial = wx.MessageDialog(None, msg, ‘Error, Save Current Data?’,

wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)

if dial.ShowModal() == wx.ID_YES:

do stuff…

else:

do other stuff…

Again, this works fine under Windows, but linux/GTK gives me a

segmentation fault when ShowModal() is called. I’ve tried changing

the parent, “None”, to be “self” and several other things, but it

would still not work. I can’t use the solution I used above, because

I need to get the result of this modal dialog. The thread must not

process anymore until ShowModal returns.

There a bunch of different ways to work with threads and wxPython
listed on the wiki:

http://wiki.wxpython.org/LongRunningTasks

Nathaniel mentioned one of them. Anyway, that page is usually the
first place to check if you need to know about threading and wx. I
think there's an example or two in the wxPython demo as well.

···

On Mar 29, 5:44 am, Teo Fonrouge <tfonro...@gmail.com> wrote:

Hello Scott,

On Mar 29, 2010, at 12:42 AM, Scott wrote:

> Hello,
> I have a question on threading with wxPython. I've started a thread
> using:
> threading.Thread(target=self.RunProgram).start()

> From within the thread, I cannot access many things outside of the
> class without getting errors. For example, see the following (self is
> a class from wx.Panel, the parent is the frame, and sb is a
> StatusBar):
> self.parent.sb.SetStatusText('Program Running...')

> I get the following error (only on Linux, it runs without problems on
> Windows):
> python: Fatal IO error 0 (Success) on X server :0.0.

> I understand that I am not supposed to code it this way and I've found
> a solution to this problem by creating a custom event, sending the
> event to the panel class that started the thread, and then having a
> separate method that updates the status. A bit long winded, but it
> works.

> However, I can't find a solution to my next problem. I want to create
> a modal dialog and have the thread wait for the response of it:
> dial = wx.MessageDialog(None, msg, 'Error, Save Current Data?',
> wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
> if dial.ShowModal() == wx.ID_YES:
> do stuff....
> else:
> do other stuff...

> Again, this works fine under Windows, but linux/GTK gives me a
> segmentation fault when ShowModal() is called. I've tried changing
> the parent, "None", to be "self" and several other things, but it
> would still not work. I can't use the solution I used above, because
> I need to get the result of this modal dialog. The thread must not
> process anymore until ShowModal returns.

> I'm new to programming with threads, can anyone point me in the right
> direction? I've tried googling for hours now without any success.

I don't have experience with wxPython, so please bear with me.

In c++ wxWidgets when you need to access the GUI library from
a thread, you need to enclose your code inside a
wxMutexGuiEnter() / wxMutexGuiLeave() block.

Seems that it also can be done with wxPython:

wxPython API Documentation — wxPython Phoenix 4.2.2 documentation

HTH

best regards,

Teo Fonrouge

-------------------
Mike Driscoll

Blog: http://blog.pythonlibrary.org

One way to do it is that the thread can create and wait on something like a threading.Event object. When the gui thread has finished showing the dialog it simply calls a method on that Event object and then in the thread control will return from the wait method. For example:

     # in the thread
     threadEvent = threading.Event()
     event = MyCustomEvent()
     event.threadEvent = threadEvent
     wx.PostEvent(thePanel, event)
     threadEvent.wait()
     # now do stuff that needs done after the dialog was dismissed
     ...

     # in the gui thread
     def OnMyCustomEvent(self, evt)
  dlg = ...
  dlg.ShowModal()
  evt.threadEvent.set()

Read the Python docs for the threading module for more information.

···

On 3/29/10 12:41 AM, Scott wrote:

Hi, thanks for your response. I spawn my thread to just run a
function within my panel class, I don't actually create a full class
from threading.Thread. Do I have to do that in your method? And how
can I set an event to a thread, do I just Connect() it as well?

--
Robin Dunn
Software Craftsman

Thanks for all of the suggestions everyone, definitely some food for
thought. I've seem that LongRunningTasks link and I've played with
several of those ideas. For my specific situation, I ended up doing a
mix of taking out some stuff that really didn't need to be done within
the thread and using the 1st method shown here (the LongRunningTasks
page):
<http://wiki.wxpython.org/LongRunningTasks&gt;

I think in general, Queues would be better, but I think for this
project the other method I'm using is quicker/cleaner/easier since I
only need two events for the thread to pass to the main wx.Panel.

Now, I only have one last problem...and now it is the Windows side
that acts up while Linux is OK. Here is the situation: When the
thread starts, a new panel in the main gui becomes active with an
"abort" button on it. When the user presses abort, a message dialog
is shown via ShowModal and it has the buttons: yes, no, and cancel. I
know how to pause the thread to wait until this message dialog is
exited, but I don't want to. I want the thread to continue processing
until the user confirms the abort.

The abort function works well for me (windows and linux)...all three
buttons behave as expected. However, if the thread ends, then I want
this dialog to automatically be dismissed (with any value since it
won't matter, but preferably wx.CANCEL). Now, I have a method that is
executed upon the ending of the thread (in the gui/panel class) from
posting an event. From this exit function I've tried calling
self.abort_dialog.EndModal(wx.CANCEL) (I put it in a try because I
know it will fail if the dialog is not currently up). On Linux, this
works well and when the thread ends, this abort dialog is dismissed.
However, on Windows, this does not work. I get an error that states
"EndModal() called for non modal dialog". I'm 110% sure that this
dialog is modal.

So how can I make this dialog go away without user intervention?

Thanks for all the help,
Scott

···

On Mar 29, 12:49 pm, Robin Dunn <ro...@alldunn.com> wrote:

On 3/29/10 12:41 AM, Scott wrote:

> Hi, thanks for your response. I spawn my thread to just run a
> function within my panel class, I don't actually create a full class
> from threading.Thread. Do I have to do that in your method? And how
> can I set an event to a thread, do I just Connect() it as well?

One way to do it is that the thread can create and wait on something
like a threading.Event object. When the gui thread has finished showing
the dialog it simply calls a method on that Event object and then in the
thread control will return from the wait method. For example:

 \# in the thread
 threadEvent = threading\.Event\(\)
 event = MyCustomEvent\(\)
 event\.threadEvent = threadEvent
 wx\.PostEvent\(thePanel, event\)
 threadEvent\.wait\(\)
 \# now do stuff that needs done after the dialog was dismissed
 \.\.\.

 \# in the gui thread
 def OnMyCustomEvent\(self, evt\)
    dlg = \.\.\.
    dlg\.ShowModal\(\)
    evt\.threadEvent\.set\(\)

Read the Python docs for the threading module for more information.

--
Robin Dunn
Software Craftsmanhttp://wxPython.org

You'll need to make a custom dialog and use it instead of the wx.MessageDialog. The wx.MessageDialog is not a real wx.Dialog but just a wrapper around the Windows API function that shows the system message dialog, and so it is not able to fully implement the wx.Dialog/wx.Window API.

···

On 3/29/10 10:33 PM, Scott wrote:

Thanks for all of the suggestions everyone, definitely some food for
thought. I've seem that LongRunningTasks link and I've played with
several of those ideas. For my specific situation, I ended up doing a
mix of taking out some stuff that really didn't need to be done within
the thread and using the 1st method shown here (the LongRunningTasks
page):
<http://wiki.wxpython.org/LongRunningTasks&gt;

I think in general, Queues would be better, but I think for this
project the other method I'm using is quicker/cleaner/easier since I
only need two events for the thread to pass to the main wx.Panel.

Now, I only have one last problem...and now it is the Windows side
that acts up while Linux is OK. Here is the situation: When the
thread starts, a new panel in the main gui becomes active with an
"abort" button on it. When the user presses abort, a message dialog
is shown via ShowModal and it has the buttons: yes, no, and cancel. I
know how to pause the thread to wait until this message dialog is
exited, but I don't want to. I want the thread to continue processing
until the user confirms the abort.

The abort function works well for me (windows and linux)...all three
buttons behave as expected. However, if the thread ends, then I want
this dialog to automatically be dismissed (with any value since it
won't matter, but preferably wx.CANCEL). Now, I have a method that is
executed upon the ending of the thread (in the gui/panel class) from
posting an event. From this exit function I've tried calling
self.abort_dialog.EndModal(wx.CANCEL) (I put it in a try because I
know it will fail if the dialog is not currently up). On Linux, this
works well and when the thread ends, this abort dialog is dismissed.
However, on Windows, this does not work. I get an error that states
"EndModal() called for non modal dialog". I'm 110% sure that this
dialog is modal.

So how can I make this dialog go away without user intervention?

--
Robin Dunn
Software Craftsman