Re: g_idle_add causing segfault from thread on exit.
- From: muppet <scott asofyet org>
- To: zentara <zentara1 sbcglobal net>
- Cc: gtk-perl-list gnome org
- Subject: Re: g_idle_add causing segfault from thread on exit.
- Date: Fri, 2 Feb 2007 21:57:10 -0500
On Feb 2, 2007, at 2:02 PM, zentara wrote:
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.
This, of course, is due to the fact that in C, you don't have
automatic reference counting controlling the lifetime of your
variables, as you do in perl.
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 ........
I ran perl in gdb, and ran the script with --g-fatal-warnings so that
the first of the warnings would call abort() and stop in the
debugger... at that point, the stack is in destruction of one of the
threads, and we're dying on an assertion from within g_object_unref().
(gdb)
#12 0x004bfd68 in XS_Glib__Object_DESTROY (my_perl=0xa0ef118,
cv=0xa1ddf24)
at GObject.xs:884
884 g_object_unref (object);
(gdb) p object->ref_count
$1 = 0
Basically, this object has already been destroyed, and what we're
seeing is a double-free.
This is consistent with my previous observations that perl duplicates
the scalars that go into spawned threads, but now we have two perl
objects pointing at the same C object, and both of them think they
own it. One thread's perl object reaches zero references and
releases the last reference to the C object, and then the second
thread's copy of that perl object reaches zero references and
attempts to release its reference to the C object. Kaboom.
So can anyone point out what I can do to quiet the mean little
error monster?
:-)
In 2004, to solve this problem, Ross put in something called "object
tracking". You set a global flag when you start up your program, and
this causes every Glib::Object instance wrapped by perl to be stored
in a hash table. Then, whenever perl clones the interpreter to
create a new thread, all Glib::Object instances that are alive and
known to perl at this point get an extra refcount bump, to avoid the
double-free problem described above.
This is not enabled by default because of the time and space penalty
it incurs. It is implemented in this clunky manner because the only
signal you get that a new thread is being created is the call to
__PACKAGE__::CLONE() in every package. It is not called on each
instance, or anything that would give you context. This does not
work for boxed types. This is not panacea. Do not taunt Happy Fun
Ball. You have been warned.
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.
*cough* fork and pipes *cough*
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/;
# make sure we don't double-free the C objects. see discussion.
Glib::Object->set_threadsafe (TRUE);
With that change, your program works fine for me.
(That said, when i tried to switch my environment to use a version of
gtk+ with debugging symbols so i could debug the crash, i didn't see
the crash even without the set_threadsafe() call. Very bizarre. YMMV.)
--
I hate to break it to you, but magic data pixies don't exist.
-- Simon Cozens
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]