summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2018-08-02 21:46:51 +0200
committerBram Moolenaar <Bram@vim.org>2018-08-02 21:46:51 +0200
commit41c363a3154dd1caeb431fa54748ad48ef6d3bd1 (patch)
tree91c64ec29455162f4f9dd54cc1ecac0a929501c3
parentded27a1febda3db7447958b60a7d791af514d124 (diff)
patch 8.1.0234: incorrect reference counting in Perl interfacev8.1.0234
Problem: Incorrect reference counting in Perl interface. Solution: Call SvREFCNT_inc more often, add a test. (Damien)
-rw-r--r--src/if_perl.xs15
-rw-r--r--src/testdir/test_perl.vim17
-rw-r--r--src/version.c2
3 files changed, 24 insertions, 10 deletions
diff --git a/src/if_perl.xs b/src/if_perl.xs
index bc15efa944..9fd219691e 100644
--- a/src/if_perl.xs
+++ b/src/if_perl.xs
@@ -831,8 +831,7 @@ newWINrv(SV *rv, win_T *ptr)
ptr->w_perl_private = newSV(0);
sv_setiv(ptr->w_perl_private, PTR2IV(ptr));
}
- else
- SvREFCNT_inc_void_NN(ptr->w_perl_private);
+ SvREFCNT_inc_void_NN(ptr->w_perl_private);
SvRV(rv) = ptr->w_perl_private;
SvROK_on(rv);
return sv_bless(rv, gv_stashpv("VIWIN", TRUE));
@@ -847,8 +846,7 @@ newBUFrv(SV *rv, buf_T *ptr)
ptr->b_perl_private = newSV(0);
sv_setiv(ptr->b_perl_private, PTR2IV(ptr));
}
- else
- SvREFCNT_inc_void_NN(ptr->b_perl_private);
+ SvREFCNT_inc_void_NN(ptr->b_perl_private);
SvRV(rv) = ptr->b_perl_private;
SvROK_on(rv);
return sv_bless(rv, gv_stashpv("VIBUF", TRUE));
@@ -918,12 +916,13 @@ I32 cur_val(IV iv, SV *sv)
else
rv = newBUFrv(newSV(0), curbuf);
- if (SvRV(sv) == SvRV(rv))
- SvREFCNT_dec(SvRV(rv));
- else // XXX: Not sure if the `else` condition are right
- // Test_SvREFCNT() pass in all case.
+ if (SvRV(sv) != SvRV(rv))
+ // XXX: This magic variable is a bit confusing...
+ // Is curently refcounted ?
sv_setsv(sv, rv);
+ SvREFCNT_dec(rv);
+
return 0;
}
#endif /* !PROTO */
diff --git a/src/testdir/test_perl.vim b/src/testdir/test_perl.vim
index 661c65cdc8..03c5fa0d10 100644
--- a/src/testdir/test_perl.vim
+++ b/src/testdir/test_perl.vim
@@ -4,6 +4,9 @@ if !has('perl')
finish
end
+" FIXME: RunTest don't see any error when Perl abort...
+perl $SIG{__WARN__} = sub { die "Unexpected warnings from perl: @_" };
+
func Test_change_buffer()
call setline(line('$'), ['1 line 1'])
perl VIM::DoCommand("normal /^1\n")
@@ -229,6 +232,15 @@ func Test_000_SvREFCNT()
#line 5 "Test_000_SvREFCNT()"
my ($b, $w);
+ my $num = 0;
+ for ( 0 .. 100 ) {
+ if ( ++$num >= 8 ) { $num = 0 }
+ VIM::DoCommand("buffer X$num");
+ $b = $curbuf;
+ }
+
+ VIM::DoCommand("buffer t");
+
$b = $curbuf for 0 .. 100;
$w = $curwin for 0 .. 100;
() = VIM::Buffers for 0 .. 100;
@@ -240,12 +252,13 @@ func Test_000_SvREFCNT()
my $cw = Internals::SvREFCNT($$w);
VIM::Eval("assert_equal(2, $cb, 'T1')");
VIM::Eval("assert_equal(2, $cw, 'T2')");
+ my $strongref;
foreach ( VIM::Buffers, VIM::Windows ) {
+ VIM::DoCommand("%bw!");
my $c = Internals::SvREFCNT($_);
VIM::Eval("assert_equal(2, $c, 'T3')");
$c = Internals::SvREFCNT($$_);
- # Why only one ref?
- # Look wrong but work. Maybe not portable...
+ next if $c == 2 && !$strongref++;
VIM::Eval("assert_equal(1, $c, 'T4')");
}
$cb = Internals::SvREFCNT($$curbuf);
diff --git a/src/version.c b/src/version.c
index 6e6c3cdc76..482b38e38a 100644
--- a/src/version.c
+++ b/src/version.c
@@ -795,6 +795,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 234,
+/**/
233,
/**/
232,