After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 319204 - 64bit problem with Gtk2::Gdk::Color properties?
64bit problem with Gtk2::Gdk::Color properties?
Status: RESOLVED FIXED
Product: gnome-perl
Classification: Bindings
Component: Gtk2
unspecified
Other Linux
: Normal normal
: ---
Assigned To: gtk2-perl-bugs
gtk2-perl-bugs
Depends on:
Blocks:
 
 
Reported: 2005-10-19 03:02 UTC by Raf D'Halleweyn
Modified: 2005-12-21 17:05 UTC
See Also:
GNOME target: ---
GNOME version: 2.11/2.12


Attachments
Patch to copy boxed values in Glib::Object::get() (3.20 KB, patch)
2005-10-22 02:43 UTC, muppet
committed Details | Review

Description Raf D'Halleweyn 2005-10-19 03:02:25 UTC
Version details: Gtk2 1.110
Distribution/Version: Ubuntu Breezy

The below program generates the wrong output when run on x86_64:

Parsed color: 1,2,3
Color from button (property): 0,0,3
Color from button (property, after set): 0,0,3
Color from selection: 1,2,3
Color from selection (property): 0,0,3

I expected that the output would be 1,2,3 for all. On i686:

Parsed color: 1,2,3
Color from button (property): 1,2,3
Color from button (property, after set): 1,2,3
Color from selection: 1,2,3
Color from selection (property): 1,2,3



#!/usr/bin/perl -w

use strict;
use Gtk2 -init;
use Glib qw(:constants);

my $color = Gtk2::Gdk::Color->parse('#010203');
print "Parsed color: ", &color2string($color), "\n";

my $color_button = Gtk2::ColorButton->new_with_color($color);
print "Color from button (property): ",
	&color2string($color_button->get('color')), "\n";
$color_button->set('color', $color);
print "Color from button (property, after set): ",
	&color2string($color_button->get('color')), "\n";

my $color_selection = Gtk2::ColorSelection->new;
$color_selection->set_current_color($color);
print "Color from selection: ",
	&color2string($color_selection->get_current_color), "\n";
print "Color from selection (property): ",
	&color2string($color_selection->get('current_color')), "\n";

sub color2string {
	join(',', map { $_[0]->$_ / 257 } qw(red green blue));
}
Comment 1 Torsten Schoenfeld 2005-10-19 17:05:20 UTC
Ouch, looks like the new converters still need some work.

In perl's CORE/config.h, what is IVTYPE defined to be on the x86_64 box?  What does

  perl -MConfig -wle'foreach (qw(use64bitall use64bitint)) { print $Config{ $_ }
|| "undef"; }'

print?
Comment 2 Raf D'Halleweyn 2005-10-19 18:14:04 UTC
x86_64$ perl -MConfig -wle'foreach (qw(use64bitall use64bitint)) { print
$Config{ $_ } || "undef"; }'
define
define
Comment 3 Torsten Schoenfeld 2005-10-20 17:29:27 UTC
And what is IVTYPE in CORE/config.h defined to be?
Comment 4 Raf D'Halleweyn 2005-10-20 20:57:58 UTC
#define IVTYPE          long            /**/
#define UVTYPE          unsigned long           /**/
#define I8TYPE          char            /**/
#define U8TYPE          unsigned char           /**/
#define I16TYPE         short   /**/
#define U16TYPE         unsigned short  /**/
#define I32TYPE         int     /**/
#define U32TYPE         unsigned int    /**/
#ifdef HAS_QUAD
#define I64TYPE         long    /**/
#define U64TYPE         unsigned long   /**/
#endif
#define NVTYPE          double          /**/
#define IVSIZE          8               /**/
#define UVSIZE          8               /**/
#define I8SIZE          1               /**/
#define U8SIZE          1               /**/
#define I16SIZE         2       /**/
#define U16SIZE         2       /**/
#define I32SIZE         4       /**/
#define U32SIZE         4       /**/
#ifdef HAS_QUAD
#define I64SIZE         8       /**/
#define U64SIZE         8       /**/
#endif
Comment 5 Torsten Schoenfeld 2005-10-21 15:44:21 UTC
Ok, your configuration matches the one I had in mind when writing the #ifdef
wrappers for the big integer converters.

The weird thing is though, that as far as I can tell, nothing in your code
should ever result in one of the 64 bit converters being called.  There's simply
nothing in there involving either gint64 or guint64.

Does the bug happen with older versions of Gtk2 as well?  Or only with 1.110?

If it only happens with 1.110, can you run this program through gdb, set
breakpoints on the converters and put the resulting backtraces here?

$ gdb perl
(gdb) r color.pl # run it once first so gdb knows about the function names
(gdb) b newSVGInt64
(gdb) b newSVGUInt64
(gdb) b SvGInt64
(gdb) b SvGUInt64
(gdb) r color.pl

Now whenever a breakpoint is reached, get the backtrace and continue:

(gdb) bt
# ...
(gdb) c

The output of 'bt' is what I'd need.
Comment 6 Raf D'Halleweyn 2005-10-21 16:39:31 UTC
I have this same problem with 1.100 as shipped by Ubuntu and 1.110 that I
compiled myself.

Like you expected, it did not hit any breakpoints.

$ gdb debugperl
GNU gdb 6.3-debian
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu"...Using host libthread_db library
"/lib/libthread_db.so.1".

(gdb) r colortest64
Starting program: /usr/bin/debugperl colortest64
[Thread debugging using libthread_db enabled]
[New Thread 46912504633040 (LWP 7384)]
Starting
Parsed color: 1,2,3
Color from button (property): 0,0,3
Color from button (property, after set): 0,0,3
Color from selection: 1,2,3
Color from selection (property): 0,0,3

Program exited normally.
(gdb) b newSVGInt64
Breakpoint 1 at 0x2aaaab434bf0
(gdb) b newSVGUInt64
Breakpoint 2 at 0x2aaaab434c40
(gdb) b SvGInt64
Breakpoint 3 at 0x2aaaab434bc0
(gdb) b SvGUInt64
Breakpoint 4 at 0x2aaaab434c10
(gdb)  r colortest64
Starting program: /usr/bin/debugperl colortest64
[Thread debugging using libthread_db enabled]
[New Thread 46912504633040 (LWP 7402)]
Starting
Parsed color: 1,2,3
Color from button (property): 0,0,3
Color from button (property, after set): 0,0,3
Color from selection: 1,2,3
Color from selection (property): 0,0,3

Program exited normally.
(gdb)
Comment 7 Raf D'Halleweyn 2005-10-21 17:47:38 UTC
I hacked a bit in GdkColor.xs to try to dump the GdkColor structure. I also
changed the colortest64 script to also output pixel.

It looks like the first 64 bits of the GdkColor are being overwritten by a
pointer. This wipes out the pixel, red and green color value.

If this is true, that would explain why it works under 32-bit, only pixel is
overwritten.

BTW, it looks like the pointer points to 16 bytes beyond the start of the GdkColor.

$ perl ../colortest64
Starting
  0x942720: 0000000001010202030300000000000000000000000000000000000000000000
  0x942720: 0000000001010202030300000000000000000000000000000000000000000000
Parsed color: 0x00000000,0x0101,0x0202,0x0303
  0x942730: 4027940000000000030396ab0000000000000000000000000303000000000000
Color from button (property): 0x00942740,0x0000,0x0000,0x0303
  0x942730: 4027940000000000030396ab0000000000000000000000000303000000000000
Color from button (property, after set): 0x00942740,0x0000,0x0000,0x0303
  0x942730: b8c67700010102020303c4aa0000000000000000000000000303000000000000
Color from selection: 0x0077c6b8,0x0101,0x0202,0x0303
  0x942730: 4027940000000000030396ab0000000000000000000000000303000000000000
Color from selection (property): 0x00942740,0x0000,0x0000,0x0303
  0x942730: b8c67700010102020303c4aa0000000000000000000000000303000000000000
Color from selection: 0x0077c6b8,0x0101,0x0202,0x0303
  0x942730: 4027940000000000030396ab0000000000000000000000000303000000000000
Color from selection (property): 0x00942740,0x0000,0x0000,0x0303

Comment 8 Raf D'Halleweyn 2005-10-21 18:00:56 UTC
This is the output on x86.

Looks like the first 32 bits of the GdkColor are overwritten with a pointer. The
pointer is 12 bytes beyond the start of the GdkColor.

Starting
  0x83b2558: 0000000001010202030300000000000000000000000000000000000000000000
  0x83b2558: 0000000001010202030300000000000000000000000000000000000000000000
Parsed color: 0x00000000,0x0101,0x0202,0x0303
  0x83b2564: 70253b0801010202030321080000000001010202030300000000000000000000
Color from button (property): 0x083b2570,0x0101,0x0202,0x0303
  0x83b2564: 70253b0801010202030321080000000001010202030300000000000000000000
Color from button (property, after set): 0x083b2570,0x0101,0x0202,0x0303
  0x83b2564: 47286c62010102020303ebbf0000000001010202030300000000000000000000
Color from selection: 0x626c2847,0x0101,0x0202,0x0303
  0x83b2564: 70253b0801010202030321080000000001010202030300000000000000000000
Color from selection (property): 0x083b2570,0x0101,0x0202,0x0303
  0x83b2564: 47286c62010102020303ebbf0000000001010202030300000000000000000000
Color from selection: 0x626c2847,0x0101,0x0202,0x0303
  0x83b2564: 70253b0801010202030321080000000001010202030300000000000000000000
Color from selection (property): 0x083b2570,0x0101,0x0202,0x0303
Comment 9 muppet 2005-10-22 02:14:36 UTC
Some notes from stepping through the source:

GdkColor is 1xsizeof(guint32)+3*sizeof(guint16) = 4+3*2 = 12 bytes.  I would not be surprised if the 
compiler padded this to 16 on ia64.

GdkColors are allocated using a GMemChunk -- that is, a fixed-size allocator.  You will see the same 
addresses over and over, and garbage from previous uses will remain in memory. 

gtk_color_selection_get_color() does not alter the value of pixel in the passed-in GdkColor; it only 
modifies red, green, and blue.

g_object_get() copies boxed objects by default.  The implementation of gdk_color_copy() bumps to the 
next free spot in the GMemChunk and then does *new_color = *color, which means that the value of 
pixel is copied in ->get(), unlike with $selection->get_color().

Gtk2 uses the default GPerlBoxedWrapperClass for dealing with GdkColors, so the pointer held by the 
sv that you see in perl actually points to another block of memory which contains the GType of the 
object, the pointer to it, and a flag that says whether we should kill the boxed object on DESTROY.
Comment 10 muppet 2005-10-22 02:43:16 UTC
Created attachment 53751 [details] [review]
Patch to copy boxed values in Glib::Object::get()

I have been contemplating this sort of change to solve other problems, but it
would be interesting to find out if this has any effect on your bug.
Comment 11 Raf D'Halleweyn 2005-10-22 04:27:15 UTC
$ perl -IGlib-1.110/blib/arch/ -IGlib-1.110/blib/lib/ -IGtk2-1.110/blib/arch/
-IGtk2-1.110/blib/lib/ colortest64
Starting
Parsed color: 0x00000000,0x0101,0x0202,0x0303
Color from button (property): 0x00951398,0x0101,0x0202,0x0303
Color from button (property, after set): 0x00951398,0x0101,0x0202,0x0303
Color from selection: 0x0077e008,0x0101,0x0202,0x0303
Color from selection (property): 0x00a179d0,0x0101,0x0202,0x0303
Color from selection: 0x0077e008,0x0101,0x0202,0x0303
Color from selection (property): 0x00a179d0,0x0101,0x0202,0x0303

:-D
Comment 12 Torsten Schoenfeld 2005-11-07 20:41:31 UTC
So, it looks like this is the correct fix.  muppet, there's an unstable release
due next week (2005-11-14).  Can you get this in before that date?

(One minor nag: gperl_sv_from_value2 isn't really descriptive.  I've no better
idea, though.  All I can come up with is _full which isn't great either.)
Comment 13 muppet 2005-11-13 02:58:55 UTC
I don't like the name, either, but a better one proves elusive.  For the time being, i'll make it a private 
function, not exported in gperl.h.
Comment 14 muppet 2005-11-13 16:50:13 UTC
Committed to HEAD.  What about stable-1-10 ?


2005/11/13	muppetman

	* GValue.xs, GObject.xs:  The GObject property interface passes around
	pointers to boxed objects, but does not transfer ownership of them.
	Thus, the old code was letting perl hold on to dead pointers.  We
	basically need to be able to specify whether to copy boxed objects
	when converting from GValue to SV.  Since gperl_sv_from_value() is
	public and API frozen, add a new private function,
	_gperl_sv_from_value_internal(), and call this from both
	gperl_sv_from_value() and Glib::Object::get().  Fixes
	http://bugzilla.gnome.org/show_bug.cgi?id=319204 and several other
	hard-to-diagnose intermittent bugs.
Comment 15 Torsten Schoenfeld 2005-11-13 17:53:08 UTC
It's a pretty important fix for 64-bit platforms, so -- yes, I think it should
go into stable-1-10 too.

Is there any way to test this stuff for regressions?
Comment 16 muppet 2005-11-13 18:09:39 UTC
Okay, committed to stable-1-10.

I have been testing whether the patch works on some bindings for another library.  It basically involves 
seeing whether you crash by trying to access dead memory.  I'm not sure there's a way to test this inside 
Glib itself without some extra XS scaffolding.  Will look into that.
Comment 17 Torsten Schoenfeld 2005-12-21 17:05:11 UTC
Closing since the bug has been fixed.