g_idle_add causing segfault from thread on exit.
- From: zentara <zentara1 sbcglobal net>
- To: gtk-perl-list gnome org
- Subject: g_idle_add causing segfault from thread on exit.
- Date: Fri, 2 Feb 2007 14:02:01 -0500
Hi,
I am trying to apply the c wisdom, from the gtk-c maillist,
to my Perl scripts.
I have found that the c handling of threads is easier to deal with
than the Perl, specifically, by allowing global variables and subs,
which the threads can access without having to declare shared vars.
Anyways, a recent discussion on the c list, generally said that the
best way to update widgets from a thread is to add a g_idle_add to
the thread. This works fine in c, and is supposedly more reliable
than the threads->enter and ->leave mechanism.
So I tried to do this in the Perl script below, and the script works
fine, but I get weird errors and a segfault when I exit. LIke:
GLib-GObject-WARNING **: instance of invalid non-instantiatable type `(null)'.
GLib-GObject-CRITICAL **: g_signal_emit_valist: assertion `G_TYPE_CHECK_INSTANCE
(instance)' failed. GLib-GObject-WARNING **: instance of invalid
non-instantiatable type `(null)'. GLib-GObject-CRITICAL **:
g_signal_handlers_destroy: assertion `G_TYPE_CHECK_INSTANCE (instance)' failed.
..... repeated several more times ........
So can anyone point out what I can do to quiet the mean little error monster?
:-)
This threaded script, violates the general wisdom of creating the thread before any
gui calls, and it allows the thread to manipulate the main's widgets. I know I can
do it other ways, but I'm searching for that "Holy Grail" of the thread safe gui usage
in Perl.
Thanks, zentara
#!/usr/bin/perl
use warnings;
use strict;
use threads;
use threads::shared;
use Glib qw/TRUE FALSE/;
use Gtk2 qw/-init -threads-init/;
#setup shared hash
my %shash;
share(%shash); #will work for first level keys
$shash{'go'} = 0;
$shash{'work'} = '';
$shash{'die'} = 0;
my $window = Gtk2::Window->new('toplevel');
$window ->signal_connect( 'destroy' => \&delete_event );
$window->set_border_width(10);
$window->set_size_request(300,300);
my $vbox = Gtk2::VBox->new( FALSE, 6 );
$window->add($vbox);
$vbox->set_border_width(2);
my $hbox= Gtk2::HBox->new( FALSE, 6 );
my $hbox1 = Gtk2::HBox->new( FALSE, 6 );
$vbox->pack_end($hbox,FALSE,FALSE,0);
$vbox->pack_end (Gtk2::HSeparator->new, FALSE, FALSE, 0);
$vbox->pack_end($hbox1,FALSE,FALSE,0);
$hbox->set_border_width(2);
$vbox->pack_end (Gtk2::HSeparator->new, FALSE, FALSE, 0);
my $ebutton = Gtk2::Button->new_from_stock('gtk-quit');
$hbox->pack_end( $ebutton, FALSE, FALSE, 0 );
$ebutton->signal_connect( clicked => \&delete_event );
my $pbar = Gtk2::ProgressBar->new();
$pbar->set_pulse_step(.1);
$hbox->pack_start($pbar,1,1,0);
my $count = 0;
my $label_w_markup = Gtk2::Label->new();
$label_w_markup->set_markup("<span foreground=\"yellow1\"
size=\"40000\">$count</span>");
$vbox->pack_end($label_w_markup,FALSE,FALSE,4);
my $tbutton = Gtk2::Button->new_with_label('Run Thread');
$hbox1->pack_start($tbutton , 1, 1, 0 );
my $lconnect = $tbutton->signal_connect( clicked => sub{ launch() });
my $sconnect;
$window->show_all();
$pbar->hide; #needs to be called after show_all
#create 1 sleeping thread passing it the label and pbar to control
my $thread = threads->new(\&work, $label_w_markup, $pbar);
Gtk2->main;
######################################
sub delete_event {
$shash{'go'} = 0;
$shash{'die'} = 1;
$thread->join;
Gtk2->main_quit;
return FALSE;
}
#######################################
sub launch{
$pbar->show;
$tbutton->set_label('Stop Thread');
$tbutton->signal_handler_block($lconnect);
$sconnect = $tbutton->signal_connect( clicked => sub{ stop() });
$shash{'go'} = 1;
}
##################################################
sub stop{
print "stopped\n";
$shash{'go'} = 0;
$pbar->hide;
$tbutton->set_label('Run Thread');
$tbutton->signal_handler_block ($sconnect);
$tbutton->signal_handler_unblock ($lconnect);
}
#########################################################
sub work{
my ($label,$pbar) = @_;
$|++;
while(1){
if($shash{'die'} == 1){ goto END };
if ( $shash{'go'} == 1 ){
foreach my $num (1..1000){
Glib::Idle->add(
sub{
if($shash{'die'} == 1){ return };
$label->set_markup("<span foreground=\"yellow1\"
size=\"40000\">$num</span>");
$pbar->pulse;
return FALSE;
});
select(undef,undef,undef, .1);
if($shash{'go'} == 0){last}
if($shash{'die'} == 1){ goto END };
}
$shash{'go'} = 0; #turn off self before returning
}else
{ select(undef,undef,undef,.1) } #sleep time
}
END:
}
#####################################################################
__END__
--
I'm not really a human, but I play one on earth.
http://zentara.net/japh.html
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]