Skip to content
This repository was archived by the owner on Jun 1, 2023. It is now read-only.

Commit 2e940da

Browse files
committed
PerlIO-via-0.17_01
1 parent 095599f commit 2e940da

File tree

5 files changed

+120
-14
lines changed

5 files changed

+120
-14
lines changed

dist/Module-CoreList/lib/Module/CoreList.pm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17558,6 +17558,7 @@ our %delta = (
1755817558
'NEXT' => '0.67_01',
1755917559
'PerlIO::encoding' => '0.26_01',
1756017560
'PerlIO::scalar' => '0.29',
17561+
'PerlIO::via' => '0.17_01',
1756117562
'List::Util' => '1.50_11',
1756217563
'List::Util::XS' => '1.50_11',
1756317564
'Scalar::Util' => '1.50_11',

ext/PerlIO-via/t/via.t

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use warnings;
1717

1818
my $tmp = "via$$";
1919

20-
use Test::More tests => 18;
20+
use Test::More tests => 26;
2121

2222
my $fh;
2323
my $a = join("", map { chr } 0..255) x 10;
@@ -44,15 +44,15 @@ is($a, $b, 'compare original data with filtered version');
4444
use warnings 'layer';
4545

4646
# Find fd number we should be using
47-
my $fd = open($fh,">$tmp") && fileno($fh);
47+
my $fd = open($fh,'>',$tmp) && fileno($fh);
4848
print $fh "Hello\n";
4949
close($fh);
5050

5151
ok( ! open($fh,">via(Unknown::Module)", $tmp), 'open via Unknown::Module will fail');
5252
like( $warnings, qr/^Cannot find package 'Unknown::Module'/, 'warn about unknown package' );
5353

5454
# Now open normally again to see if we get right fileno
55-
my $fd2 = open($fh,"<$tmp") && fileno($fh);
55+
my $fd2 = open($fh,'<',$tmp) && fileno($fh);
5656
is($fd2,$fd,"Wrong fd number after failed open");
5757

5858
my $data = <$fh>;
@@ -84,6 +84,60 @@ is( $obj, 'Foo', 'search for package Foo' );
8484
open $fh, '<:via(Bar)', "bar";
8585
is( $obj, 'PerlIO::via::Bar', 'search for package PerlIO::via::Bar' );
8686

87+
{
88+
# [perl #131221]
89+
ok(open(my $fh1, ">", $tmp), "open $tmp");
90+
ok(binmode($fh1, ":via(XXX)"), "binmode :via(XXX) onto it");
91+
ok(open(my $fh2, ">&", $fh1), "dup it");
92+
close $fh1;
93+
close $fh2;
94+
95+
# make sure the old workaround still works
96+
ok(open($fh1, ">", $tmp), "open $tmp");
97+
ok(binmode($fh1, ":via(YYY)"), "binmode :via(YYY) onto it");
98+
ok(open($fh2, ">&", $fh1), "dup it");
99+
print $fh2 "XZXZ";
100+
close $fh1;
101+
close $fh2;
102+
103+
ok(open($fh1, "<", $tmp), "open $tmp for check");
104+
{ local $/; $b = <$fh1> }
105+
close $fh1;
106+
is($b, "XZXZ", "check result is from non-filtering class");
107+
108+
package PerlIO::via::XXX;
109+
110+
sub PUSHED {
111+
my $class = shift;
112+
bless {}, $class;
113+
}
114+
115+
sub WRITE {
116+
my ($self, $buffer, $handle) = @_;
117+
118+
print $handle $buffer;
119+
return length($buffer);
120+
}
121+
package PerlIO::via::YYY;
122+
123+
sub PUSHED {
124+
my $class = shift;
125+
bless {}, $class;
126+
}
127+
128+
sub WRITE {
129+
my ($self, $buffer, $handle) = @_;
130+
131+
$buffer =~ tr/X/Y/;
132+
print $handle $buffer;
133+
return length($buffer);
134+
}
135+
136+
sub GETARG {
137+
"XXX";
138+
}
139+
}
140+
87141
END {
88142
1 while unlink $tmp;
89143
}

ext/PerlIO-via/via.pm

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package PerlIO::via;
2-
our $VERSION = '0.16';
2+
our $VERSION = '0.17_01';
3+
our $XS_VERSION = $VERSION;
4+
$VERSION = eval $VERSION;
35
require XSLoader;
46
XSLoader::load();
57
1;

ext/PerlIO-via/via.xs

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ typedef struct
3838
CV *UTF8;
3939
} PerlIOVia;
4040

41+
static const MGVTBL PerlIOVia_tag = { 0, 0, 0, 0, 0, 0, 0, 0 };
42+
4143
#define MYMethod(x) #x,&s->x
4244

4345
static CV *
@@ -97,10 +99,8 @@ PerlIOVia_method(pTHX_ PerlIO * f, const char *method, CV ** save, int flags,
9799
GvIOp(gv) = newIO();
98100
s->fh = newRV((SV *) gv);
99101
s->io = GvIOp(gv);
100-
if (gv) {
101-
/* shamelessly stolen from IO::File's new_tmpfile() */
102-
(void) hv_delete(GvSTASH(gv), GvNAME(gv), GvNAMELEN(gv), G_DISCARD);
103-
}
102+
/* shamelessly stolen from IO::File's new_tmpfile() */
103+
(void) hv_delete(GvSTASH(gv), GvNAME(gv), GvNAMELEN(gv), G_DISCARD);
104104
}
105105
IoIFP(s->io) = PerlIONext(f);
106106
IoOFP(s->io) = PerlIONext(f);
@@ -131,8 +131,14 @@ PerlIOVia_pushed(pTHX_ PerlIO * f, const char *mode, SV * arg,
131131
PerlIO_funcs * tab)
132132
{
133133
IV code = PerlIOBase_pushed(aTHX_ f, mode, Nullsv, tab);
134+
135+
if (arg && SvTYPE(arg) >= SVt_PVMG
136+
&& mg_findext(arg, PERL_MAGIC_ext, &PerlIOVia_tag)) {
137+
return code;
138+
}
139+
134140
if (code == 0) {
135-
PerlIOVia *s = PerlIOSelf(f, PerlIOVia);
141+
PerlIOVia *s = PerlIOSelf(f, PerlIOVia);
136142
if (!arg) {
137143
if (ckWARN(WARN_LAYER))
138144
Perl_warner(aTHX_ packWARN(WARN_LAYER),
@@ -583,20 +589,59 @@ static SV *
583589
PerlIOVia_getarg(pTHX_ PerlIO * f, CLONE_PARAMS * param, int flags)
584590
{
585591
PerlIOVia *s = PerlIOSelf(f, PerlIOVia);
586-
PERL_UNUSED_ARG(param);
592+
SV *arg;
587593
PERL_UNUSED_ARG(flags);
588-
return PerlIOVia_method(aTHX_ f, MYMethod(GETARG), G_SCALAR, Nullsv);
594+
595+
/* During cloning, return an undef token object so that _pushed() knows
596+
* that it should not call methods and wait for _dup() to actually dup the
597+
* object. */
598+
if (param) {
599+
SV *sv = newSV(0);
600+
sv_magicext(sv, NULL, PERL_MAGIC_ext, &PerlIOVia_tag, 0, 0);
601+
return sv;
602+
}
603+
604+
arg = PerlIOVia_method(aTHX_ f, MYMethod(GETARG), G_SCALAR, Nullsv);
605+
if (arg) {
606+
/* arg is a temp, and PerlIOBase_dup() will explicitly free it */
607+
SvREFCNT_inc(arg);
608+
}
609+
else {
610+
arg = newSVpvn(HvNAME(s->stash), HvNAMELEN(s->stash));
611+
}
612+
613+
return arg;
589614
}
590615

591616
static PerlIO *
592617
PerlIOVia_dup(pTHX_ PerlIO * f, PerlIO * o, CLONE_PARAMS * param,
593618
int flags)
594619
{
595620
if ((f = PerlIOBase_dup(aTHX_ f, o, param, flags))) {
596-
/* Most of the fields will lazily set themselves up as needed
597-
stash and obj have been set up by the implied push
598-
*/
621+
#ifdef USE_ITHREADS
622+
if (param) {
623+
/* For a non-interpreter dup stash and obj have been set up
624+
by the implied push.
625+
626+
But if this is a clone for a new interpreter we need to
627+
translate the objects to their dups.
628+
*/
629+
630+
PerlIOVia *fs = PerlIOSelf(f, PerlIOVia);
631+
PerlIOVia *os = PerlIOSelf(o, PerlIOVia);
632+
633+
fs->obj = sv_dup_inc(os->obj, param);
634+
fs->stash = (HV*)sv_dup((SV*)os->stash, param);
635+
fs->var = sv_dup_inc(os->var, param);
636+
fs->cnt = os->cnt;
637+
638+
/* fh, io, cached CVs left as NULL, PerlIOVia_method()
639+
will reinitialize them if needed */
640+
}
641+
#endif
642+
/* for a non-threaded dup fs->obj and stash should be set by _pushed() */
599643
}
644+
600645
return f;
601646
}
602647

pod/perlcdelta.pod

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,10 @@ check invariant at compile time.
438438

439439
return EACCES on writing to a read-only scalar
440440

441+
=item L<PerlIO::via> 0.17_01
442+
443+
Protect from NULL arg.
444+
441445
=item Scalar-List-Util 1.50_11
442446

443447
fix C<find_rundefsvoffset> logic.

0 commit comments

Comments
 (0)