Bizarre intermittent behavior in Tk::Pod - this one is deep. 
Author Message
 Bizarre intermittent behavior in Tk::Pod - this one is deep.

Yes, yes, following up to my own post...
I'm also cross-posting to comp.lang.perl.misc because the conclusion I
reached does not have anything to do with Tk, per se, but instead how
perl compares references.

Quote:

> I am observing a problem which is really taxing my ability to debug.  I
> have an application where if you push a button, you get a pod widget
> window to provide "on-line help".

> The button press intermittently fails with a message like:

> Tk::Error: Can't set -labelRelief to `flat' for
> Tk::LabEntry=HASH(0x800000010171deb8): Bad option `-labelRelief'

> Now the point is that it is truly intermittent.  "Most" of the time it
> works just fine, but occasionally I get the above message, although the
> actual option and widget it is complaining about varies from failure to
> failure.

> I was able to reproduce it with the following:

> HPUX 11.0> /usr/perl/5.6.1/bin/perl -de 1
> Default die handler restored.

> Loading DB routines from perl5db.pl version 1.07
> Editor support available.

> Enter h or `h h' for help, or `man perldebug' for more help.

> main::(-e:1):   1
>   DB<1> require Tk::Pod;


>   DB<3> *Tk::Pod::Text::head4 = \&Tk::Pod::Text::head2;

>   DB<5> $mw=MainWindow->new

>   DB<6> $mw->Pod(-file=>'foobar.pod');

> # it pops up just fine, so
> # here I forcibly close the window.

>   DB<7> $mw->update

> # and it closes.

>   DB<8> $mw->Pod(-file=>'foobar.pod');

> # it pops up just fine, so
> # here I forcibly close the window.

>   DB<9> $mw->update

> # and it closes.

>   DB<10> $mw->Pod(-file=>'foobar.pod');

> ## it pops up just fine, so
>  here I forcibly close the window.

>   DB<11> $mw->update

> # and it closes.

>   DB<12> $mw->Pod(-file=>'foobar.pod');
> Can't set -scrollbars to `w' for Tk::Pod::Text=HASH(0x8000000100a85d58):
> Bad option `-scrollbars' at /usr/perl/5.6.1/lib/Tk/Configure.pm line 46,
> <> line 398.
>  at /usr/perl/5.6.1/lib/Tk/Derived.pm line 294

>  at /usr/perl/5.6.1/lib/Tk/Derived.pm line 306

> # And there is no window

>   DB<13> $mw->Pod(-file=>'foobar.pod');

> # and yet again, it pops up fine.

> I put a print action at Tk::Configure::configure and this is what I get
> in the passing case:

> In configure, called with _configure _cget
> Tk::Frame=HASH(0x800000010179a0f0) -foreground -foreground Black
> In configure, called with Tk::configure Tk::cget
> Tk::Frame=HASH(0x800000010179a0f0) -background -background #d9d9d9
> In configure, called with Tk::configure Tk::cget
> Tk::Frame=HASH(0x800000010179a0f0)
> In configure, called with configure cget
> Tk::Label=HASH(0x8000000101711070) -highlightcolor -labelHighlightcolor
> Black
> In configure, called with configure cget
> Tk::Label=HASH(0x8000000101711070) -justify -labelJustify center
> In configure, called with configure cget
> Tk::Label=HASH(0x8000000101711070) -height -labelHeight 0
> In configure, called with configure cget
> Tk::Label=HASH(0x8000000101711070) -offset -labelOffset 0 0
> In configure, called with _configure _cget
> Tk::LabEntry=HASH(0x80000001016c2e28) -foreground -foreground Black
> In configure, called with configure cget
> Tk::Label=HASH(0x8000000101711070) -cursor -labelCursor
> In configure, called with configure cget
> Tk::Label=HASH(0x8000000101711070) -highlightbackground
> -labelHighlightbackground #d9d9d9
> In configure, called with labelPack labelPack
> Tk::LabEntry=HASH(0x80000001016c2e28) -labelPack
> ARRAY(0x80000001016ebf38)
> In configure, called with configure cget
> Tk::Label=HASH(0x8000000101711070) -font -labelFont Helvetica -12 bold
> In configure, called with Tk::configure Tk::cget
> Tk::LabEntry=HASH(0x80000001016c2e28) -background -background #d9d9d9
> In configure, called with configure cget
> Tk::Label=HASH(0x8000000101711070) -foreground -labelForeground Black

> etc. ad nauseum

> But in the failing case I get:

> In configure, called with Tk::configure Tk::cget
> Tk::Frame=HASH(0x800000010161bb30) -background -background #d9d9d9
> In configure, called with _configure _cget
> Tk::Frame=HASH(0x800000010161bb30) -foreground -foreground Black
> In configure, called with Tk::configure Tk::cget
> Tk::Frame=HASH(0x800000010161bb30)
> In configure, called with configure cget
> Tk::Label=HASH(0x8000000101762870) -highlightcolor -labelHighlightcolor
> Black
> In configure, called with configure cget
> Tk::Label=HASH(0x8000000101762870) -justify -labelJustify center
> In configure, called with configure cget
> Tk::Label=HASH(0x8000000101762870) -height -labelHeight 0
> In configure, called with configure cget
> Tk::Label=HASH(0x8000000101762870) -offset -labelOffset 0 0
> In configure, called with _configure _cget
> Tk::LabEntry=HASH(0x8000000101768a00) -foreground -foreground Black
> In configure, called with configure cget
> Tk::Label=HASH(0x8000000101762870) -cursor -labelCursor
> In configure, called with configure cget
> Tk::Label=HASH(0x8000000101762870) -highlightbackground
> -labelHighlightbackground #d9d9d9
> In configure, called with labelPack labelPack
> Tk::LabEntry=HASH(0x8000000101768a00) -labelPack
> ARRAY(0x8000000101768940)
> In configure, called with configure cget
> Tk::Label=HASH(0x8000000101762870) -font -labelFont Helvetica -12 bold
> In configure, called with Tk::configure Tk::cget
> Tk::LabEntry=HASH(0x8000000101768a00) -background -background #d9d9d9
> In configure, called with Tk::configure Tk::cget
> Tk::LabEntry=HASH(0x8000000101768a00) -labelForeground -labelForeground
> Black
> Tk::Error: Can't set -labelForeground to `Black' for
> Tk::LabEntry=HASH(0x8000000101768a00): Bad option `-labelForeground' at
> [traceback]

> Now if you compare the last two lines of the failing and passing cases:

> configure cget Tk::Label=HASH() -foreground -labelForeground Black
> Tk::configure Tk::cget Tk::LabEntry=HASH() -labelForeground
> -labelForeground Black

> One can guess that what was supposed to happen is that the LabEntry was
> supposed to be looked up in the configspecs hash and the
> -labelForeground entry was supposed to tell some piece of code to change
> the -foreground option of the Label subwidget, but somehow this
> translation silently failed and the translation simply returned itself.

> Since this is "supposed" to be deterministic, the only thing I can
> figure is that something is reading out a hash and since the order of
> hash reads may vary, this possibly could explain why it is
> "intermittent".  However, I'm way deep in over my head into Tk::Derived
> and composite widgets and all of the magic behind configuration
> management and, frankly, I'm getting lost.

> Can anybody explain *what* is happening?  Can anybody supply a patch?

I put in a whole bunch of actions and turned tracing on in the de{*filter*}
to see if I could catch it in the act of behaving differently.

I believe the problem is in this snippet of code:

 foreach $widget (_makelist($widget))
  {
   $widget = 'SELF' if (ref($widget) && $widget == $cw);

Which is in Tk::Derived::Subconfigure.

I instrumented this specific line of code and got this result:

81:      foreach $widget (_makelist($widget))
82:       {
Tk::LabEntry=HASH(0x8000000101967f18) -labelRelief
$VAR1 = bless( [
                 'configure',
                 'cget',
                 bless( {
                          '_TkValue_' =>
'.pod.pod.frame.more.labentry.label'
                        }, 'Tk::Label' ),
                 '-relief'
               ], 'Tk::Configure' );
Tk::Derived::_makelist(/usr/intel/pkgs/perl/5.6.1/lib/site_perl/5.6.1/PA-RISC2.0/Tk/Derived.pm:42):
42:      my $widget = shift;
Tk::Derived::_makelist(/usr/intel/pkgs/perl/5.6.1/lib/site_perl/5.6.1/PA-RISC2.0/Tk/Derived.pm:43):

Tk::Derived::_makelist(/usr/intel/pkgs/perl/5.6.1/lib/site_perl/5.6.1/PA-RISC2.0/Tk/Derived.pm:44):

Tk::Derived::Subconfigure(/usr/intel/pkgs/perl/5.6.1/lib/site_perl/5.6.1/PA-RISC2.0/Tk/Derived.pm:83):
83:        $widget = 'SELF' if (ref($widget) && $widget == $cw);
widget == cw (Tk::Configure=ARRAY(0x8000000101967c58) ==
Tk::LabEntry=HASH(0x8000000101967f18): 1 boolean: 1
Tk::Derived::Subconfigure(/usr/intel/pkgs/perl/5.6.1/lib/site_perl/5.6.1/PA-RISC2.0/Tk/Derived.pm:84):
84:        if (ref $widget)
85:         {
Tk::Derived::Subconfigure(/usr/intel/pkgs/perl/5.6.1/lib/site_perl/5.6.1/PA-RISC2.0/Tk/Derived.pm:131):


Tk::Configure::new(/usr/intel/pkgs/perl/5.6.1/lib/site_perl/5.6.1/PA-RISC2.0/Tk/Configure.pm:18):

Tk::Configure::new(/usr/intel/pkgs/perl/5.6.1/lib/site_perl/5.6.1/PA-RISC2.0/Tk/Configure.pm:19):

Tk::Configure::new(/usr/intel/pkgs/perl/5.6.1/lib/site_perl/5.6.1/PA-RISC2.0/Tk/Configure.pm:20):

Tk::Derived::Subconfigure(/usr/intel/pkgs/perl/5.6.1/lib/site_perl/5.6.1/PA-RISC2.0/Tk/Derived.pm:81):
81:      foreach $widget (_makelist($widget))
82:       {
Tk::LabEntry=HASH(0x8000000101967f18) -labelRelief
$VAR1 = 'SELF';

Now this shows that Tk::Derived::Subconfigure is working through the
subwidgets looking for the appropriate doohicky to configure, and if the
doohicky is itself, it changes the widget to 'SELF'.  However the line
of code is:

 $widget = 'SELF' if (ref($widget) && $widget == $cw);

and there is a general belief in the perl community that references,
when used in a numeric context, coerce to numbers based on their address
value.  However, the instrumentation clearly shows that the comparison
of ($widget == $cw) was TRUE even though it *should* have been FALSE.
This was on the line:

widget == cw (Tk::Configure=ARRAY(0x8000000101967c58) ==
Tk::LabEntry=HASH(0x8000000101967f18)): 1 boolean: 1

So since the comparison is ...

read more »



Wed, 15 Sep 2004 00:15:06 GMT  
 Bizarre intermittent behavior in Tk::Pod - this one is deep.


Quote:
> Does anybody have any experience in these matters who can comment on
> what is happening and can answer the following questions:

> - Exactly what happens when you numerically compare references on a
> PARISC 2.0?
> - Why does the test show TRUE when clearly it should be false?
> - Is this a generic problem or a problem specific to my
> OS/platform/compiler?
> - Does this (numeric comparison of references) happen a lot in the Tk
> libraries?  How about other libraries?
> - What should I do to fix this?

> Any help would be greatly appreciated.

I don't have the answers to the above, but when I've compared
references, I've always used 'eq', i.e. comparing the "stringized" form.  
Perhaps that would help you here?
--
Kevin Michael Vail | a billion stars go spinning through the night,

. . . . . . . . .  | But _in_ you is the presence that
 . . . . . . . . . | will be, when all the stars are dead.  (Rainer Maria Rilke)


Wed, 15 Sep 2004 03:30:21 GMT  
 Bizarre intermittent behavior in Tk::Pod - this one is deep.
[big snip]

Quote:
> Now this shows that Tk::Derived::Subconfigure is working through the
> subwidgets looking for the appropriate doohicky to configure, and if
> the doohicky is itself, it changes the widget to 'SELF'.  However the
> line of code is:

>  $widget = 'SELF' if (ref($widget) && $widget == $cw);

> and there is a general belief in the perl community that references,
> when used in a numeric context, coerce to numbers based on their
> address value.  However, the instrumentation clearly shows that the
> comparison of ($widget == $cw) was TRUE even though it *should* have
> been FALSE.
> This was on the line:

> widget == cw (Tk::Configure=ARRAY(0x8000000101967c58) ==
> Tk::LabEntry=HASH(0x8000000101967f18)): 1 boolean: 1

That looks so WRONG.  Definitely a bug in perl.

Quote:
> So since the comparison is TRUE, $widget is replaced with 'SELF',
> which is wrong.  This goes to the point of comparing reference
> addresses and just exactly how that gets done.  Notice that on a newer
> HPUX machine we have a 64-bit address, but this does not necessarily
> imply that we have a 64 bit integer value to put it in.

> One alternative is to coerce the address into a floating point value,
> but there may be some kind of loss of precision in this case, causing
> the values to match.

> When I look through the rest of Tk::Derived I notice other lines where
> widgets are being numerically compared and this raises the question in
> my mind if there are other places where this incorrect comparison can
> occur.

Hmm, no, I think that doing a numeric comparison is the proper thing to
do in almost all situations.  It's not an "incorrect comparison" except
insofar as that perl is doing it wrong.

Quote:
> When I do a -V option on the perl I get the following interesting
> factoids:

>  Characteristics of this binary (from libperl):
>   Compile-time options: USE_64_BIT_INT USE_64_BIT_ALL USE_LARGE_FILES
>   Built under hpux

> which tells me we should have 64 bit integers, and since a 64 bit
> address works with a 64 bit integer, we should have no problem.  Yet
> we clearly do.

Right.  Use 'perlbug' to send in a report.

Quote:
> Does anybody have any experience in these matters who can comment on
> what is happening and can answer the following questions:

> - Exactly what happens when you numerically compare references on a
> PARISC 2.0?

Perl is carefully designed to be compilable on multiple platforms, and
the only way to figure out "exactly what happens" is to look at perl's
source, and examine the #ifdefs, and learn which things are #defined on
your platform, and learn what types are typedefed to other types.

Hmm... well, that'll at least should what *should* happen, but the only
way to know what *does* happen is to run it in the de{*filter*} (gdb or the
equivilant, that is, not just the perl de{*filter*}).

Quote:
> - Why does the test show TRUE when clearly it should be false?

Possibly it's only using the top 32 bits of the address when doing the
conversion from pointer to integer.... or something.

Quote:
> - Is this a generic problem or a problem specific to my
> OS/platform/compiler?

Well, I doubt it exists on machines which do everything in 32 bits :)

Maybe it is, maybe it isn't.  Likey it's the particular combination of
32-bitness and 64-bitness that your combo of OS/platform/compiler uses,
but it might exist on other machines.

Quote:
> - Does this (numeric comparison of references) happen a lot in the Tk
> libraries?  How about other libraries?

Yes.  Numeric comparison of references is the normal, "correct" way to
do it.

Quote:
> - What should I do to fix this?

Report the bug to the p5p mailing list (The reports produced by the
"perlbug" program get sent there automatically), and see what they say
in response.

The most likely fix is to upgrade your perl... see if it occurs when
using 5.7.3.

It would help if you could write a short perl script which demonstrates
the problem.

Here's an attempt [untested... I'm not on your platform, so I've no clue
what the results would be there]:

my %foo;
while(1) {
   my $foo = "x" x 12345678;
   my $bar = \$foo + 0;
   $foo{ $bar }
      and die "Collision: $foo and $foo{$bar} both == $bar\n";
   $foo{ $bar } = \$foo;

Quote:
}

Unless it overruns your memory first, this will, hopefully, find any
collision that might occur.

Tweaking the size of the string in $foo may be necessary.

--
print reverse( ",rekcah", " lreP", " rehtona", " tsuJ" )."\n";



Sun, 19 Sep 2004 09:46:13 GMT  
 Bizarre intermittent behavior in Tk::Pod - this one is deep.
[A complimentary Cc of this posting was sent to
The Small Kahuna

Quote:
>  $widget = 'SELF' if (ref($widget) && $widget == $cw);

> and there is a general belief in the perl community that references,
> when used in a numeric context, coerce to numbers based on their address
> value.

... unless numify-overloading strikes you...

Quote:
> However, the instrumentation clearly shows that the comparison
> of ($widget == $cw) was TRUE even though it *should* have been FALSE.
> This was on the line:

> widget == cw (Tk::Configure=ARRAY(0x8000000101967c58) ==
> Tk::LabEntry=HASH(0x8000000101967f18)): 1 boolean: 1

> So since the comparison is TRUE, $widget is replaced with 'SELF', which
> is wrong.  This goes to the point of comparing reference addresses and
> just exactly how that gets done.  Notice that on a newer HPUX machine we
> have a 64-bit address, but this does not necessarily imply that we have
> a 64 bit integer value to put it in.

Yes, it does necessarily imply that we have a 64 bit integer value to
put it in.  However, it does not necessarily imply that == is
performed on integers.  I suspect that (on your architecture?) ==
coerces to double, thus fails.

And I do not know whether `use integer' affects ==...  Vgrepping
opcode.pl... Yes, there are separate eq and i_eq opcodes.  Thus
putting `use integer' should help.

Hope this helps,
Ilya



Sun, 19 Sep 2004 12:00:07 GMT  
 Bizarre intermittent behavior in Tk::Pod - this one is deep.
Benjamin:

You might recall this 20-days-ago answer
you wrote (I'll include a bit so that you
*can* recall it).

What I'm interested in being explained
is not this problem and the sending in of
the bug, but just that little test loop
at the end.



Quote:

>[big snip]
>> Now this shows that Tk::Derived::Subconfigure is working through the
>> subwidgets looking for the appropriate doohicky to configure, and if
>> the doohicky is itself, it changes the widget to 'SELF'.  However the
>> line of code is:

>>  $widget = 'SELF' if (ref($widget) && $widget == $cw);

>> and there is a general belief in the perl community that references,
>> when used in a numeric context, coerce to numbers based on their
>> address value.  However, the instrumentation clearly shows that the
>> comparison of ($widget == $cw) was TRUE even though it *should* have
>> been FALSE.
>> This was on the line:

>> widget == cw (Tk::Configure=ARRAY(0x8000000101967c58) ==
>> Tk::LabEntry=HASH(0x8000000101967f18)): 1 boolean: 1

>That looks so WRONG.  Definitely a bug in perl.

BIG SNIP

- Show quoted text -

Quote:
>It would help if you could write a short perl script which demonstrates
>the problem.

>Here's an attempt [untested... I'm not on your platform, so I've no clue
>what the results would be there]:

>my %foo;
>while(1) {
>   my $foo = "x" x 12345678;
>   my $bar = \$foo + 0;
>   $foo{ $bar }
>      and die "Collision: $foo and $foo{$bar} both == $bar\n";
>   $foo{ $bar } = \$foo;
>}

>Unless it overruns your memory first, this will, hopefully, find any
>collision that might occur.

>Tweaking the size of the string in $foo may be necessary.

Could you please explain what that routine is
trying to do, and also the code that is to
do it?

The way I read it, $foo gets this monster string
of "xxxxx...xxxx", 12 million chars long.

Then $bar gets the numerical address of that string.

THEN (maybe I haven't had enough sleep), it looks
like foo's being treated as a hash -- or I'm just
being fooled by the syntax.

(I'm sure I'm missing something!)

Anyway, how does a non-zero result imply a collision?

And then how does that statement just after
the die make the whole thing work?

Looks like something pretty neat, but I don't
understand on bit of it!

THANKS!

David



Thu, 07 Oct 2004 04:45:41 GMT  
 Bizarre intermittent behavior in Tk::Pod - this one is deep.
[snip... two references to different objects comparing == when they
shouldn't be.]

Quote:
> >Here's an attempt [untested... I'm not on your platform, so I've no
> >clue what the results would be there]:

> >my %foo;
> >while(1) {
> >   my $foo = "x" x 12345678;
> >   my $bar = \$foo + 0;
> >   $foo{ $bar }
> >      and die "Collision: $foo and $foo{$bar} both == $bar\n";
> >   $foo{ $bar } = \$foo;
> >}

> >Unless it overruns your memory first, this will, hopefully, find any
> >collision that might occur.

> >Tweaking the size of the string in $foo may be necessary.

> Could you please explain what that routine is trying to do,
> and also the code that is to do it?

> The way I read it, $foo gets this monster string
> of "xxxxx...xxxx", 12 million chars long.

> Then $bar gets the numerical address of that string.

The numerical value of a reference to the scalar, but yes, more or less.

The purpose of this is to bump up addresses as quickly as possible.

Quote:
> THEN (maybe I haven't had enough sleep), it looks
> like foo's being treated as a hash -- or I'm just
> being fooled by the syntax.

Err, it's using the %foo hash declared above the loop, which has nothing
to do with $foo.  Maybe I should have used another name?

Quote:
> (I'm sure I'm missing something!)

> Anyway, how does a non-zero result imply a collision?

Well, think of it this way.  When would there already be an entry in
%foo for the number $bar?

Quote:
> And then how does that statement just after
> the die make the whole thing work?

This sticks an entry for $bar into the hash %foo.

Quote:
> Looks like something pretty neat, but I don't
> understand on bit of it!

Maybe it'll be more understandable if I wrote it as this:

my %baz;
while(1) {
   # allocate lots of memory so the pointers will be big numbers
   # The big block bumps up the addresses alot.  The three small
   # ones should all have very similar addresses.
   for my $size ( 3**19, 1, 1, 1 ) {
      my $foo = "x" x $size;
      my $bar = \$foo + 0;
      defined( $baz{$bar} )
         and die sprintf <<"", \$foo, $baz{ $bar }, $bar;
            Collision: %s and %s are both numerically equal to %s.
      $baz{ $bar } = \$foo;
   }

Quote:
}

PS: It's not really important that you get this code to show the bug...
The reason for it has been discovered... if 'use integer' hasn't been
enabled, then the numeric value of a reference is a double, not an
integer, and if your pointer addresses have more significant bits than
your double type, then precision is lost, and two references which have
very large addresses which are similar in their least significant bits
will end up as being considered equal according to ==.

Just enable 'use integer' in the scope of the == comparison of
references to fix the problem.

--
print reverse( ",rekcah", " lreP", " rehtona", " tsuJ" )."\n";



Thu, 07 Oct 2004 08:18:07 GMT  
 
 [ 6 post ] 

 Relevant Pages 

1. Bizarre intermittent behavior in Tk::Pod - this one is deep.

2. What causes this bizarre hash behavior?

3. Bizarre mod_perl behavior

4. bizarre PERL/CGI behavior question

5. bizarre REQUIRE behavior

6. Truly bizarre do FILE behavior

7. bizarre $var->method behavior

8. Bizarre regexp behavior (bug?)

9. Tk::Pod does not resolve link to standard perl pod

10. Problem using Tk::Pod to read embedded POD

11. Pod::Filter, Pod::Usage, and Pod::PlainText now on CPAN

12. Pod Problems (using =pod, nesting fonts, and Pod::Text)

 

 
Powered by phpBB® Forum Software