Subject: | workaround for 5.15.<0-6> hash bug |
Date: | Tue, 18 Jul 2017 05:05:49 +0100 |
To: | bug-Package-Stash-XS [...] rt.cpan.org |
From: | Zefram <zefram [...] fysh.org> |
There's a hash bug in some old versions of the Perl core that
Package::Stash::XS could helpfully work around. The attached patch
does so.
The bug is concerned with the timing of the freeing of a value deleted
from a hash when hv_delete_ent() is passed the G_DISCARD flag. From Perl
version 5.15.0 to 5.15.6 inclusive, the value would have its refcount
decreased before actually being removed from the hash, so if the value
has a destructor and that causes some operation on the hash then it sees
the hash in an inconsistent state and mayhem can ensue.
The bug is fiendishly difficult to invoke by anything other than a very
artificial test case, which explains why it tends to go unnoticed.
The situation in which I've actually run into it is that the use
of G_DISCARD in Package::Stash::XS->remove_glob causes a failure
in namespace::autoclean's test suite. (namespace::autoclean uses
namespace::clean, which uses Package::Stash::XS. Neither namespace::clean
nor Package::Stash::XS notice the problem in their test suites.)
In addition to the patch, I'm attaching a test script which tickles
the bug, using only Package::Stash::XS and B::Hooks::EndOfScope.
It's derived from namespace::autoclean's failing test, by minimisation
and the incorporation of the relevant parts of namespace::autoclean
and namespace::clean. This test is almost suitable for adding to
Package::Stash::XS's test suite, but unfortunately I haven't been able
to eliminate the use of B::Hooks::EndOfScope from it, and that would be
a new dependency for Package::Stash::XS.
Of course, the affected Perl versions are only development versions,
and are nominally obsolete, so the impact of this problem is limited.
But it is useful to test modules against old dev versions, especially
when a module has version-dependent problems, in which case seeing which
dev versions are affected is very revealing. I therefore like to keep as
much infrastructure as possible working on those old versions that aren't
total lemons. Quite a few modules these days use namespace::autoclean,
and testing those on old versions is how I ran into this problem.
-zefram
Message body is not shown because sender requested not to inline it.
Message body is not shown because sender requested not to inline it.