diff options
-rw-r--r-- | ext/PerlIO-scalar/scalar.xs | 13 | ||||
-rw-r--r-- | ext/PerlIO-scalar/t/scalar.t | 16 |
2 files changed, 26 insertions, 3 deletions
diff --git a/ext/PerlIO-scalar/scalar.xs b/ext/PerlIO-scalar/scalar.xs index eac682b5c3..87c5682388 100644 --- a/ext/PerlIO-scalar/scalar.xs +++ b/ext/PerlIO-scalar/scalar.xs @@ -314,12 +314,21 @@ PerlIO * PerlIOScalar_dup(pTHX_ PerlIO * f, PerlIO * o, CLONE_PARAMS * param, int flags) { + /* Duplication causes the scalar layer to be pushed on to clone, caus- + ing the cloned scalar to be set to the empty string by + PerlIOScalar_pushed. So set aside our scalar temporarily. */ + PerlIOScalar * const os = PerlIOSelf(o, PerlIOScalar); + SV * const var = os->var; + os->var = newSVpvs(""); if ((f = PerlIOBase_dup(aTHX_ f, o, param, flags))) { PerlIOScalar *fs = PerlIOSelf(f, PerlIOScalar); - PerlIOScalar *os = PerlIOSelf(o, PerlIOScalar); - /* var has been set by implicit push */ + /* var has been set by implicit push, so replace it */ + SvREFCNT_dec(fs->var); + fs->var = PerlIO_sv_dup(aTHX_ var, param); fs->posn = os->posn; } + SvREFCNT_dec(os->var); + os->var = var; return f; } diff --git a/ext/PerlIO-scalar/t/scalar.t b/ext/PerlIO-scalar/t/scalar.t index a02107b17d..18bbda9404 100644 --- a/ext/PerlIO-scalar/t/scalar.t +++ b/ext/PerlIO-scalar/t/scalar.t @@ -16,7 +16,7 @@ use Fcntl qw(SEEK_SET SEEK_CUR SEEK_END); # Not 0, 1, 2 everywhere. $| = 1; -use Test::More tests => 79; +use Test::More tests => 81; my $fh; my $var = "aaa\n"; @@ -360,3 +360,17 @@ SKIP: { ok has_trailing_nul $memfile, 'write appends null when growing string after seek past end'; } + +# [perl #112780] Cloning of in-memory handles +SKIP: { + skip "no threads", 2 if !$Config::Config{useithreads}; + require threads; + my $str = ''; + open my $fh, ">", \$str; + $str = 'a'; + is scalar threads::async(sub { my $foo = $str; $foo })->join, "a", + 'scalars behind in-memory handles are cloned properly'; + print $fh "a"; + is scalar async { print $fh "b"; $str }->join, "ab", + 'printing to a cloned in-memory handle works'; +} |