GTK2 crash after multi-threading joined
- From: Hominid He <hominidhe 163 com>
- To: gtk-perl-list gnome org
- Subject: GTK2 crash after multi-threading joined
- Date: Wed, 17 Jan 2007 16:37:23 +0800
Hi, all.
I use threads to call LWP functions for non-blocking GTK2 gui:
#! /usr/bin/perl -w
package main;
use strict;
use warnings;
use URI::Heuristic;
use threads;
use Gtk2 qw/-init -threads-init/;
use Glib qw/TRUE FALSE/;
die "Glib::Object thread safetly failed"
unless Glib::Object->set_threadsafe(TRUE);
my $raw_url;
my $url;
my $window = Gtk2::Window->new('toplevel');
$window->signal_connect('delete_event' => sub
{
my @joinable = threads->list(threads::joinable);
while(my $thr = shift @joinable)
{
$thr->join;
}
my @running = threads->list(threads::running);
while(my $thr = shift @running)
{
$thr->kill('KILL')->detach();
}
Gtk2->main_quit;
});
my $vbox = Gtk2::VBox->new(FALSE, 4);
$window->add($vbox);
my $label = new Gtk2::Label;
$vbox->pack_start($label, 0, 0, 4);
my $entry = new Gtk2::Entry;
$vbox->pack_start($entry, 0, 0, 4);
my $go = Gtk2::Button->new('_Go');
$vbox->pack_start($go, 0, 0, 4);
$go->signal_connect(clicked => sub
{
$go->set_sensitive(FALSE);
$raw_url = $entry->get_text;
$url = URI::Heuristic::uf_urlstr($raw_url);
my $worker = Worker->new($url, $label);
my $timer = Glib::Timeout->add(100, sub
{
if($worker->{child}->is_joinable())
{
$worker->{child}->join;
print "Thread ".$worker->{child}->tid." was
joined.\n";
$go->set_sensitive(TRUE);
return FALSE;
}
else
{
return TRUE;
}
}
);
}
);
$window->show_all();
Gtk2->main();
package Worker;
use strict;
use warnings;
use threads;
use LWP::Simple;
use LWP::UserAgent;
use Glib qw(TRUE FALSE);
sub new
{
my $class = shift;
my ($url, $label) = @_;
my $self = ();
$self->{url} = $url;
$self->{label} = $label;
bless $self, $class;
$self->{child} = threads->new(\&_worker_thread, $self);
return $self;
}
sub _worker_thread
{
my $self = shift;
my $thread = threads->self;
print "Thread ".$thread->tid." started.\n";
my $res;
my $url = $self->{url};
my $label = $self->{label};
my $ua = LWP::UserAgent->new
(
agent => "Test UserAgent",
keep_alive => 1,
env_proxy => 1,
timeout => 10,
);
$thread->yield();
my $header = $ua->head($url);
if($header->is_error())
{
$res = "Error: ".$header->status_line."\n";
}
else
{
$res = $header->headers_as_string."\n";
}
Gtk2::Gdk::Threads->enter;
$label->set_text($res);
Gtk2::Gdk::Threads->leave;
print "Thread ".$thread->tid." ended\n";
}
It works well, but when I create the Worker thread twice:
#! /usr/bin/perl -w
package main;
use strict;
use warnings;
use URI::Heuristic;
use threads;
use Gtk2 qw/-init -threads-init/;
use Glib qw/TRUE FALSE/;
die "Glib::Object thread safetly failed"
unless Glib::Object->set_threadsafe(TRUE);
my $raw_url;
my $raw_url2;
my $url;
my $url2;
my $window = Gtk2::Window->new('toplevel');
$window->signal_connect('delete_event' => sub
{
my @joinable = threads->list(threads::joinable);
while(my $thr = shift @joinable)
{
$thr->join;
}
my @running = threads->list(threads::running);
while(my $thr = shift @running)
{
$thr->kill('KILL')->detach();
}
Gtk2->main_quit;
});
my $vbox = Gtk2::VBox->new(FALSE, 4);
$window->add($vbox);
my $label = new Gtk2::Label;
$vbox->pack_start($label, 0, 0, 4);
my $entry = new Gtk2::Entry;
$vbox->pack_start($entry, 0, 0, 4);
my $go = Gtk2::Button->new('_Go');
$vbox->pack_start($go, 0, 0, 4);
$go->signal_connect(clicked => sub
{
$go->set_sensitive(FALSE);
$raw_url = $entry->get_text;
$url = URI::Heuristic::uf_urlstr($raw_url);
my $worker = Worker->new($url, $label);
my $timer = Glib::Timeout->add(100, sub
{
if($worker->{child}->is_joinable())
{
$worker->{child}->join;
print "Thread ".$worker->{child}->tid." was
joined.\n";
$go->set_sensitive(TRUE);
return FALSE;
}
else
{
return TRUE;
}
}
);
}
);
my $label2 = new Gtk2::Label;
$vbox->pack_start($label2, 0, 0, 0);
my $entry2 = new Gtk2::Entry;
$vbox->pack_start($entry2, 0, 0, 0);
my $go2 = Gtk2::Button->new('_Go2');
$vbox->pack_start($go2, 0, 0, 0);
$go2->signal_connect(clicked => sub
{
$go2->set_sensitive(FALSE);
$raw_url2 = $entry2->get_text;
$url2 = URI::Heuristic::uf_urlstr($raw_url2);
my $worker2 = Worker->new($url2, $label2);
my $timer2 = Glib::Timeout->add(100, sub
{
if($worker2->{child}->is_joinable())
{
$worker2->{child}->join;
print "Thread ".$worker2->{child}->tid." was
joined.\n";
$go2->set_sensitive(TRUE);
return FALSE;
}
else
{
return TRUE;
}
}
);
}
);
$window->show_all();
Gtk2->main();
package Worker;
use strict;
use warnings;
use threads;
use LWP::Simple;
use LWP::UserAgent;
use Glib qw(TRUE FALSE);
sub new
{
my $class = shift;
my ($url, $label) = @_;
my $self;
$self->{url} = $url;
$self->{label} = $label;
bless $self, $class;
$self->{child} = threads->new(\&_worker_thread, $self);
return $self;
}
sub _worker_thread
{
my $self = shift;
my $thread = threads->self;
print "Thread ".$thread->tid." started.\n";
my $res;
my $url = $self->{url};
my $label = $self->{label};
$thread->yield();
my $ua = LWP::UserAgent->new
(
agent => "Test UserAgent",
keep_alive => 1,
env_proxy => 1,
timeout => 10,
);
my $header = $ua->head($url);
if($header->is_error())
{
$res = "Error: ".$header->status_line."\n";
}
else
{
$res = $header->headers_as_string."\n";
}
Gtk2::Gdk::Threads->enter;
$label->set_text($res);
Gtk2::Gdk::Threads->leave;
print "Thread ".$thread->tid." ended.\n";
}
It was crashed when I click the two "Go" buttons alternately:
Thread 1 started.
Thread 1 ended.
Thread 1 was joined.
Thread 2 started.
Thread 2 ended.
Thread 2 was joined.
Thread 3 started.
Thread 3 ended.
Thread 3 was joined.
Thread 4 started.
Thread 4 ended.
Thread 4 was joined.
Thread 5 started.
Thread 5 ended.
GLib-GObject-WARNING **: instance with invalid (NULL) class pointer
during global destruction.
GLib-GObject-CRITICAL **: g_signal_emit_valist: assertion
`G_TYPE_CHECK_INSTANCE (instance)' failed during global destruction.
GLib-GObject-WARNING **: instance with invalid (NULL) class pointer
during global destruction.
GLib-GObject-CRITICAL **: g_signal_handlers_destroy: assertion
`G_TYPE_CHECK_INSTANCE (instance)' failed during global destruction.
GLib-GObject-WARNING **: instance with invalid (NULL) class pointer
during global destruction.
GLib-GObject-CRITICAL **: g_signal_handlers_destroy: assertion
`G_TYPE_CHECK_INSTANCE (instance)' failed during global destruction.
Scalars leaked: -27
Thread 5 was joined.
How can I re-create thread in GTK2-Perl? Thanks all.
--
Hominid He <hominidhe 163 com>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]