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]