Thread safety and dialogs

Hello. I’m writing a ruby/gtk2 application scheduling application
for my university, which does some work in a separate thread,
to keep the UI usable. That separate thread might fail, in which
case I’d like to show an error dialog back in the UI. Now, I’ve
tried this without exceptions first (though I’d rather have it use
exceptions), like this:

def do_scheduling # called by the event
Thread.new do
success = long_complicated_task
unless success
error_dialog “Scheduling unsuccessful”
else

end
end
end

def error_dialog(msg)
dialog = Gtk::MessageDialog.new nil,
Gtk::Dialog::MODAL | Gtk::Dialog::DESTROY_WITH_PARENT,
Gtk::MessageDialog::ERROR, Gtk::MessageDialog::BUTTONS_OK, msg
dialog.run
dialog.destroy
end

Now, I’ve had this dialog fail on me, but I can’t reproduce it
(threads will be threads…). Something about another thread already
being in the mainloop. How can I secure myself against this?


Protect your digital freedom and privacy, eliminate DRM, learn more at
http://www.defectivebydesign.org/what_is_drm

Ohad L.


Using Tomcat but need to do more? Need to support web services,
security?
Get stuff done quickly with pre-integrated technology to make your job
easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache
Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

Ohad L. wrote:

Hello. I’m writing a ruby/gtk2 application scheduling application
for my university, which does some work in a separate thread,
to keep the UI usable. That separate thread might fail, in which
case I’d like to show an error dialog back in the UI. Now, I’ve
tried this without exceptions first (though I’d rather have it use
exceptions), like this:

I think someone should write a FAQ.

AFAIK you simply cannot create two mainloops, so you can’t fire a dialog
from a different ruby thread. You can instead set some sahred variable
and
fire the dialog from the main thread.

AFAIU this is a GTK limitation (the GTK main loop can’t contain another
one
in the same thread, and ruby threads are not real system threads).


Mirko M.
Ubuntu: an African word meaning “I can’t figure out how to configure
Debian”


Using Tomcat but need to do more? Need to support web services,
security?
Get stuff done quickly with pre-integrated technology to make your job
easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache
Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

On Wed, Oct 18, 2006 at 02:28:28PM +0200, Ohad L. wrote:

Now, I’ve had this dialog fail on me, but I can’t reproduce it
(threads will be threads…). Something about another thread already
being in the mainloop. How can I secure myself against this?

What worked fine for me so far is just doing it in an idle handler.
I don’t know if this is really thread-safe, and I gather that idle
handlers
are almost always a bad thing, but anyway, it would look something like
this:

def error_dialog(msg)
Gtk.idle_add do
dialog = Gtk::MessageDialog.new nil,
Gtk::Dialog::MODAL | Gtk::Dialog::DESTROY_WITH_PARENT,
Gtk::MessageDialog::ERROR, Gtk::MessageDialog::BUTTONS_OK, msg
dialog.run
dialog.destroy
false
end
end

That false on the last line is important, or else it will loop.

hth,
Markus


Using Tomcat but need to do more? Need to support web services,
security?
Get stuff done quickly with pre-integrated technology to make your job
easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache
Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

On 10/18/06, Mirko M. [email protected] wrote:

AFAIK you simply cannot create two mainloops, so you can’t fire a dialog
from a different ruby thread. You can instead set some sahred variable and
fire the dialog from the main thread.

For the record and to possibly help other readers:

I wholeheartedly agree with Mirko. I’ve had some aborts in my
application “booh” because of this problem. I’ve tried to solve the
problem (with the help of Mirko) down to the application level (at the
Gtk level actually), but my message was never replied:

http://mail.gnome.org/archives/gtk-devel-list/2005-June/msg00025.html

Hence, I’ve workarounded the problem in my program by using a data
structure to send Gtk method calls to the main Thread. The following
explains it:

  1. on startup, from the main thread, create a mutex and a timeout loop
    which will perform the Gtk method calls:

    $protect_gtk_pending_calls = Mutex.new
    $gtk_pending_calls = []
    Gtk.timeout_add(100) {
    $protect_gtk_pending_calls.synchronize {
    for closure in $gtk_pending_calls
    closure.call
    end
    $gtk_pending_calls = []
    }
    true
    }

  2. add a method called whenever some Gtk method calls are desired:

def gtk_thread_protect(&proc)
if Thread.current == Thread.main
proc.call
else
$protect_gtk_pending_calls.synchronize {
$gtk_pending_calls << proc
}
end
end

For example, when refreshing a progress bar value doing a heavy
computation from within a separate ruby thread:

            gtk_thread_protect { pb.fraction = value }
  1. add a method to flush pending Gtk method calls, to be used when
    some Gtk objects are about to be destroyed on which pending Gtk method
    calls may be undone yet

def gtk_thread_flush
#- try to lock. we cannot synchronize blindly because this might
be called from
#- within the timeout flushing procs. if this is the case, not
doing anything
#- should be ok since the timeout is already flushing them all.
if $protect_gtk_pending_calls.try_lock
for closure in $gtk_pending_calls
closure.call
end
$gtk_pending_calls = []
$protect_gtk_pending_calls.unlock
end
end


Guillaume C. - Guillaume Cottenceau


Using Tomcat but need to do more? Need to support web services,
security?
Get stuff done quickly with pre-integrated technology to make your job
easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache
Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

I’ve found that this works too, without using the idle loop - instead
of using ‘run’, using ‘show’ and connection the ‘response’ signal to
dialog.destroy.

On 10/18/06, Markus K. [email protected] wrote:

 Gtk.idle_add do

ruby-gnome2-devel-en mailing list
[email protected]
ruby-gnome2-devel-en List Signup and Options


Protect your digital freedom and privacy, eliminate DRM, learn more at
http://www.defectivebydesign.org/what_is_drm

Ohad L.


Using Tomcat but need to do more? Need to support web services,
security?
Get stuff done quickly with pre-integrated technology to make your job
easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache
Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642