Remove improper use of each() in B::walksymtable and fix ext/B/t/xref.t
authorYves Orton <demerphq@gmail.com>
Wed, 21 Nov 2012 22:45:24 +0000 (23:45 +0100)
committerYves Orton <demerphq@gmail.com>
Wed, 21 Nov 2012 23:11:20 +0000 (00:11 +0100)
commit5cc8528c900964306cba9b53c6eaa27af540eaea
treed7c2fa48219a1b4e2ce4a85a68e64ff3280083eb
parentc31ee3bbc31a4f8c5b4850ce38fb8c353dca688f
Remove improper use of each() in B::walksymtable and fix ext/B/t/xref.t

Improper use of each() in walksymtable() makes behavior undefined.

As of the hash randomization patch ext/B/t/xref.t would occasionally
fail. A closer inspection revealed that the output that is parsed
in t/xref.t would vary greatly from run to run, with bizarre double
entries and sometimes missing packages, etc. So in 100 runs we would see
something like 25 of one variant, and then 25 of another, and then about
50 singletons. The notable difference between the two large groups is
that one was missing entire modules worth of output, the other appeared
to be correct. The singletons tended to differ from one of the other
two by a line or two.

Changing the each() to a keys() appears to fix this bug, making the
output consistent every time. My theory is that it is possible for the
symbol table logic to recurse and enter the same package twice, which
would result in its each iterator changing state but I have not verfied
this.  In order to make sure that the traversal order is deterministic
I decided to use sort(keys()) (In other words the sort() is there to
guarantee a given output in the future, not to fix this bug).

Annoyingly many times the test would pass even though the output it was
parsing was grossly wrong. I think we need to figure out a better way to
test this module. We should probably check for the presence of various
packages, like the B package itsef, Errno.pm etc.

I cannot explain yet why this bug was sensitive to build options.
My normal build options seemed to not have any issue, wheras others did.

Apparently ok (with or without -Dusethreads):
    git clean -dfX; ./Configure -Doptimize=-g -d -Dusedevel -Dusethreads
        -Dprefix=~/bleadperl -Dcc=ccache\ gcc -Dld=gcc -DDEBUGGING

Regular fails:
    git clean -dfx; ./Configure -des -Dusedevel -Dprefix=~/bleadperl
        -Dcc=ccache\ gcc -Dld=gcc

My tests used the following one liners:

    for file in test{1..100}; do ./perl -Ilib ext/B/t/xref.t > $file 2>&1; done;
    md5sum test* | sort | uniq -c -w32 | sort -n
ext/B/B.pm
ext/B/t/xref.t