[perl #71076] sort with active sub (5.10 regression)
Father Chrysostomos [Mon, 7 Dec 2009 13:58:40 +0000 (14:58 +0100)]
One of the tests in sort.t causes a bus error (or sometimes ‘Undefined
subroutine called’) if run multiple times. This is because sort
decreases the refcount of an active sub used as a comparison routine.

Ironically enough, this test was added by the very change that broke it
(25953/9850bf2).

pp_sort.c
t/op/sort.t

index a657fa7..12e77f9 100644 (file)
--- a/pp_sort.c
+++ b/pp_sort.c
@@ -1652,6 +1652,11 @@ PP(pp_sort)
            if (!(flags & OPf_SPECIAL)) {
                cx->cx_type = CXt_SUB;
                cx->blk_gimme = G_SCALAR;
+               /* If our comparison routine is already active (CvDEPTH is
+                * is not 0),  then PUSHSUB does not increase the refcount,
+                * so we have to do it ourselves, because the LEAVESUB fur-
+                * ther down lowers it. */
+               if (CvDEPTH(cv)) SvREFCNT_inc_simple_void_NN(cv);
                PUSHSUB(cx);
                if (!is_xsub) {
                    AV* const padlist = CvPADLIST(cv);
index 75b9a17..24e1713 100644 (file)
@@ -6,7 +6,7 @@ BEGIN {
     require 'test.pl';
 }
 use warnings;
-plan( tests => 147 );
+plan( tests => 148 );
 
 # these shouldn't hang
 {
@@ -701,8 +701,8 @@ $fail_msg = q(Can't undef active subroutine);
 cmp_ok(substr($@,0,length($fail_msg)),'eq',$fail_msg,'undef active subr');
 
 
-
-{
+for(1,2) # We run this twice, to make sure sort does not lower the ref
+{        # count. See bug 71076.
     my $failed = 0;
 
     sub rec {