summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dist/threads-shared/shared.xs24
-rw-r--r--dist/threads-shared/t/object2.t43
2 files changed, 64 insertions, 3 deletions
diff --git a/dist/threads-shared/shared.xs b/dist/threads-shared/shared.xs
index 8e41139b02..162a3d7028 100644
--- a/dist/threads-shared/shared.xs
+++ b/dist/threads-shared/shared.xs
@@ -1371,9 +1371,29 @@ void
STORESIZE(SV *obj,IV count)
CODE:
dTHXc;
- SV *sobj = SHAREDSV_FROM_OBJ(obj);
+ SV *ssv = SHAREDSV_FROM_OBJ(obj);
+
SHARED_EDIT;
- av_fill((AV*) sobj, count - 1);
+ assert(SvTYPE(ssv) == SVt_PVAV);
+ if (!PL_dirty) {
+ SV **svp = AvARRAY((AV *)ssv);
+ I32 ix = AvFILLp((AV *)ssv);
+ for (;ix >= count; ix--) {
+ SV *sv = svp[ix];
+ if (!sv)
+ continue;
+ if ( (SvOBJECT(sv) || (SvROK(sv) && (sv = SvRV(sv))))
+ && SvREFCNT(sv) == 1 )
+ {
+ SV *tmp = Perl_sv_newmortal(caller_perl);
+ PERL_SET_CONTEXT((aTHX = caller_perl));
+ sv_upgrade(tmp, SVt_RV);
+ get_RV(tmp, sv);
+ PERL_SET_CONTEXT((aTHX = PL_sharedsv_space));
+ }
+ }
+ }
+ av_fill((AV*) ssv, count - 1);
SHARED_RELEASE;
diff --git a/dist/threads-shared/t/object2.t b/dist/threads-shared/t/object2.t
index f59bad8d27..3d795b9208 100644
--- a/dist/threads-shared/t/object2.t
+++ b/dist/threads-shared/t/object2.t
@@ -17,7 +17,7 @@ use ExtUtils::testlib;
BEGIN {
$| = 1;
- print("1..122\n"); ### Number of tests that will be run ###
+ print("1..131\n"); ### Number of tests that will be run ###
};
use threads;
@@ -406,4 +406,45 @@ ok($destroyed[$ID], 'Scalar object removed from undef shared hash');
}
ok($destroyed[$ID], 'Scalar object removed from shared scalar');
+#
+# RT #122950 abandoning array elements (e.g. by setting $#ary)
+# should trigger destructors
+
+{
+ package rt122950;
+
+ my $count = 0;
+ sub DESTROY { $count++ }
+
+ my $n = 4;
+
+ for my $type (0..1) {
+ my @a : shared;
+ $count = 0;
+ push @a, bless &threads::shared::share({}) for 1..$n;
+ for (1..$n) {
+ { # new scope to ensure tmps are freed, destructors called
+ if ($type) {
+ pop @a;
+ }
+ else {
+ $#a = $n - $_ - 1;
+ }
+ }
+ ::ok($count == $_,
+ "remove array object $_ by " . ($type ? "pop" : '$#a=N'));
+ }
+ }
+
+ my @a : shared;
+ $count = 0;
+ push @a, bless &threads::shared::share({}) for 1..$n;
+ {
+ undef @a; # this is implemented internally as $#a = -01
+ }
+ ::ok($count == $n, "remove array object by undef");
+}
+
+
+
# EOF