Skip to content

Commit f37395a

Browse files
committed
cpan/Tie-RefHash - Update to version 1.41
1.41 2024-08-25 22:32:19Z - fix leaks in @thread_object_registry (RT#64025, tusooa, #1 and Lukas Mai, #2) - fix incompatibility with Scalar::Util 1.65 and remove old refaddr fallback (Lukas Mai, #3)
1 parent 34d9693 commit f37395a

File tree

3 files changed

+52
-34
lines changed

3 files changed

+52
-34
lines changed

Porting/Maintainers.pl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1211,7 +1211,8 @@ package Maintainers;
12111211
},
12121212

12131213
'Tie::RefHash' => {
1214-
'DISTRIBUTION' => 'ETHER/Tie-RefHash-1.40.tar.gz',
1214+
'DISTRIBUTION' => 'ETHER/Tie-RefHash-1.41.tar.gz',
1215+
'SYNCINFO' => 'mauke on Mon Aug 26 04:28:51 2024',
12151216
'FILES' => q[cpan/Tie-RefHash],
12161217
'EXCLUDED' => [
12171218
qr{^t/00-},

cpan/Tie-RefHash/lib/Tie/RefHash.pm

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
package Tie::RefHash; # git description: Tie-RefHash-1.39-10-g2cfa4bd
1+
package Tie::RefHash; # git description: v1.40-9-g23812d9
22
# ABSTRACT: Use references as hash keys
33

4-
our $VERSION = '1.40';
4+
our $VERSION = '1.41';
55

66
#pod =head1 SYNOPSIS
77
#pod
@@ -76,36 +76,18 @@ our @ISA = qw(Tie::Hash);
7676
use strict;
7777
use Carp ();
7878

79+
# Tie::RefHash::Weak (until at least 0.09) assumes we define a refaddr()
80+
# function, so just import the one from Scalar::Util
81+
use Scalar::Util qw(refaddr);
82+
7983
BEGIN {
80-
local $@;
8184
# determine whether we need to take care of threads
8285
use Config ();
8386
my $usethreads = $Config::Config{usethreads}; # && exists $INC{"threads.pm"}
8487
*_HAS_THREADS = $usethreads ? sub () { 1 } : sub () { 0 };
85-
*_HAS_SCALAR_UTIL = eval { require Scalar::Util; 1 } ? sub () { 1 } : sub () { 0 };
8688
*_HAS_WEAKEN = defined(&Scalar::Util::weaken) ? sub () { 1 } : sub () { 0 };
8789
}
8890

89-
BEGIN {
90-
# create a refaddr function
91-
92-
local $@;
93-
94-
if ( _HAS_SCALAR_UTIL ) {
95-
*refaddr = sub { goto \&Scalar::Util::refaddr }
96-
} else {
97-
require overload;
98-
99-
*refaddr = sub {
100-
if ( overload::StrVal($_[0]) =~ /\( 0x ([a-zA-Z0-9]+) \)$/x) {
101-
return $1;
102-
} else {
103-
die "couldn't parse StrVal: " . overload::StrVal($_[0]);
104-
}
105-
};
106-
}
107-
}
108-
10991
my (@thread_object_registry, $count); # used by the CLONE method to rehash the keys after their refaddr changed
11092

11193
sub TIEHASH {
@@ -127,6 +109,7 @@ sub TIEHASH {
127109
if ( ++$count > 1000 ) {
128110
# this ensures we don't fill up with a huge array dead weakrefs
129111
@thread_object_registry = grep defined, @thread_object_registry;
112+
Scalar::Util::weaken( $_ ) for @thread_object_registry;
130113
$count = 0;
131114
}
132115
} else {
@@ -164,19 +147,20 @@ sub CLONE {
164147
# when the thread has been cloned all the objects need to be updated.
165148
# dead weakrefs are undefined, so we filter them out
166149
@thread_object_registry = grep defined && do { $_->_reindex_keys; 1 }, @thread_object_registry;
150+
Scalar::Util::weaken( $_ ) for @thread_object_registry;
167151
$count = 0; # we just cleaned up
168152
}
169153

170154
sub _reindex_keys {
171155
my ( $self, $extra_keys ) = @_;
172156
# rehash all the ref keys based on their new StrVal
173-
%{ $self->[0] } = map +(Scalar::Util::refaddr($_->[0]) => $_), (values(%{ $self->[0] }), @{ $extra_keys || [] });
157+
%{ $self->[0] } = map +(refaddr($_->[0]) => $_), (values(%{ $self->[0] }), @{ $extra_keys || [] });
174158
}
175159

176160
sub FETCH {
177161
my($s, $k) = @_;
178162
if (ref $k) {
179-
my $kstr = Scalar::Util::refaddr($k);
163+
my $kstr = refaddr($k);
180164
if (defined $s->[0]{$kstr}) {
181165
$s->[0]{$kstr}[1];
182166
}
@@ -192,7 +176,7 @@ sub FETCH {
192176
sub STORE {
193177
my($s, $k, $v) = @_;
194178
if (ref $k) {
195-
$s->[0]{Scalar::Util::refaddr($k)} = [$k, $v];
179+
$s->[0]{refaddr($k)} = [$k, $v];
196180
}
197181
else {
198182
$s->[1]{$k} = $v;
@@ -203,13 +187,13 @@ sub STORE {
203187
sub DELETE {
204188
my($s, $k) = @_;
205189
(ref $k)
206-
? (delete($s->[0]{Scalar::Util::refaddr($k)}) || [])->[1]
190+
? (delete($s->[0]{refaddr($k)}) || [])->[1]
207191
: delete($s->[1]{$k});
208192
}
209193

210194
sub EXISTS {
211195
my($s, $k) = @_;
212-
(ref $k) ? exists($s->[0]{Scalar::Util::refaddr($k)}) : exists($s->[1]{$k});
196+
(ref $k) ? exists($s->[0]{refaddr($k)}) : exists($s->[1]{$k});
213197
}
214198

215199
sub FIRSTKEY {
@@ -268,7 +252,7 @@ Tie::RefHash - Use references as hash keys
268252
269253
=head1 VERSION
270254
271-
version 1.40
255+
version 1.41
272256
273257
=head1 SYNOPSIS
274258
@@ -343,7 +327,7 @@ Tie::RefHash::Nestable by Ed Avis <ed@membled.com>
343327
344328
=head1 CONTRIBUTORS
345329
346-
=for stopwords Yuval Kogman Karen Etheridge Florian Ragwitz Jerry D. Hedden
330+
=for stopwords Yuval Kogman Karen Etheridge Florian Ragwitz Lukas Mai Jerry D. Hedden tusooa
347331
348332
=over 4
349333
@@ -361,8 +345,16 @@ Florian Ragwitz <rafl@debian.org>
361345
362346
=item *
363347
348+
Lukas Mai <lukasmai.403@gmail.com>
349+
350+
=item *
351+
364352
Jerry D. Hedden <jdhedden@cpan.org>
365353
354+
=item *
355+
356+
tusooa <tusooa@kazv.moe>
357+
366358
=back
367359
368360
=head1 COPYRIGHT AND LICENCE

cpan/Tie-RefHash/t/threaded.t

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use strict;
1313
BEGIN {
1414
# this is sucky because threads.pm has to be loaded before Test::Builder
1515
use Config;
16-
eval { require Scalar::Util };
1716

1817
if ( $^O eq 'MSWin32' ) {
1918
print "1..0 # Skip -- this test is generally broken on windows for unknown reasons. If you can help debug this patches would be very welcome.\n";
@@ -22,13 +21,14 @@ BEGIN {
2221
if ( $Config{usethreads} and !$Config{use5005threads}
2322
and eval { +require threads; threads->import; 1 }
2423
) {
25-
print "1..14\n";
24+
print "1..18\n";
2625
} else {
2726
print "1..0 # Skip -- threads aren't enabled in your perl";
2827
exit 0;
2928
}
3029
}
3130

31+
use Scalar::Util qw(weaken);
3232
use Tie::RefHash;
3333

3434
$\ = "\n";
@@ -74,3 +74,28 @@ $th->join;
7474
is( $hash{$v1}, "string", "fetch by string after clone, orig thread ($v1)" );
7575
is( $hash{$r1}, "hash", "fetch by ref after clone ($r1)" );
7676
is( $hash{$r2}, "array", "fetch by ref after clone ($r2)" );
77+
78+
{
79+
# RT 64025
80+
81+
my $ref;
82+
{
83+
tie my %local_hash, "Tie::RefHash";
84+
$ref = tied %local_hash;
85+
weaken $ref;
86+
is( ref($ref), "Tie::RefHash", "[attempt 1] tie object exists" );
87+
}
88+
ok( !defined($ref), "[attempt 2] tie object is gone after hash goes out of scope" );
89+
90+
{
91+
tie my %local_hash, "Tie::RefHash";
92+
$ref = tied %local_hash;
93+
weaken $ref;
94+
is( ref($ref), "Tie::RefHash", "[attempt 2] tie object exists" );
95+
96+
for my $i (1 .. 1_000) {
97+
tie my %tmp, "Tie::RefHash"; # churn
98+
}
99+
}
100+
ok( !defined($ref), "[attempt 2] tie object is gone after hash goes out of scope" );
101+
}

0 commit comments

Comments
 (0)