Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tied filehandles need a PerlIO::get_layers interface #11784

Open
p5pRT opened this issue Dec 3, 2011 · 10 comments
Open

Tied filehandles need a PerlIO::get_layers interface #11784

p5pRT opened this issue Dec 3, 2011 · 10 comments

Comments

@p5pRT
Copy link

p5pRT commented Dec 3, 2011

Migrated from rt.perl.org#105232 (status was 'open')

Searchable as RT105232$

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2011

From @xdg

Created by @xdg

Tied filehandles have BINMODE to modify layers on filehandle,
but no corresponding interface to query the layers already on the
filehandle.

Tied filehandles should support a GET_LAYERS method that
PerlIO​::get_layers would then use to retrieve layers from
tied filehandles.

This change to core would also require updating Tie​::Handle
and Tie​::StdHandle accordingly.

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.14.0:

Configured by david at Mon Jun  6 22:42:49 EDT 2011.

Summary of my perl5 (revision 5 version 14 subversion 0) configuration:

  Platform:
    osname=linux, osvers=2.6.35-28-generic, archname=x86_64-linux
    uname='linux icarus 2.6.35-28-generic #50-ubuntu smp fri mar 18
18:42:20 utc 2011 x86_64 gnulinux '
    config_args='-de -Dprefix=/home/david/perl5/perlbrew/perls/perl-5.14.0'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-fno-strict-aliasing -pipe -fstack-protector
-I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2',
    cppflags='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.4.5', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t',
lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /lib/../lib /usr/lib/../lib /lib /usr/lib
/usr/lib/x86_64-linux-gnu /lib64 /usr/lib64
    libs=-lnsl -ldl -lm -lcrypt -lutil -lc
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
    libc=/lib/libc-2.12.1.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.12.1'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib
-fstack-protector'

Locally applied patches:



@INC for perl 5.14.0:
    /home/david/perl5/perlbrew/perls/perl-5.14.0/lib/site_perl/5.14.0/x86_64-linux
    /home/david/perl5/perlbrew/perls/perl-5.14.0/lib/site_perl/5.14.0
    /home/david/perl5/perlbrew/perls/perl-5.14.0/lib/5.14.0/x86_64-linux
    /home/david/perl5/perlbrew/perls/perl-5.14.0/lib/5.14.0
    .


Environment for perl 5.14.0:
    HOME=/home/david
    LANG=en_US.utf8
    LANGUAGE (unset)
    LC_COLLATE=C
    LC_CTYPE=en_US.UTF-8
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=~/git/utility-scripts/:/home/david/perl5/perlbrew/bin:/home/david/perl5/perlbrew/perls/perl-5.14.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:.
    PERLBREW_BASHRC_VERSION=0.30
    PERLBREW_HOME=/home/david/.perlbrew
    PERLBREW_PATH=/home/david/perl5/perlbrew/bin:/home/david/perl5/perlbrew/perls/perl-5.14.0/bin
    PERLBREW_PERL=perl-5.14.0
    PERLBREW_ROOT=/home/david/perl5/perlbrew
    PERLBREW_VERSION=0.23
    PERL_BADLANG (unset)
    PERL_EXTUTILS_AUTOINSTALL=--defaultdeps
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2011

From @Hugmeir

This should probably be called GETARG, since that's what PerlIO​::via uses.

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2011

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2011

From @xdg

On Fri, Dec 2, 2011 at 10​:13 PM, Brian Fraser <fraserbn@​gmail.com> wrote​:

This should probably be called GETARG, since that's what PerlIO​::via uses.

I don't see how that relates.

Tie *STDOUT with Tie​::StdHandle. Apply "​:utf8" to it with binmode
(which dispatches to BINMODE). Then call PerlIO​::get_layers on it.
You won't see the "​:utf8" layer that you just applied.

N.B. you *can* see the "​:utf8" layer if you do this​:

  PerlIO​::get_layers(tied *STDOUT) if tied(*STDOUT) && (reftype tied
*STDOUT eq 'GLOB');

That's unreasonably breaks the intended transparency of tied handles.
You shouldn't have to check whether a handle is tied (and is
implemented via a glob) to request layers on it.

A tied filehandle needs to have a method that PerlIO​::get_layers can
use to request the underlying layers. Since every other tied handle
method mirrors the corresponding built-in call, I suggest GET_LAYERS.
PerlIO​::get_layers is not a built-in, but it's the what we have for
inspecting layers on a filehandle.

In Tie​::StdHandle, it would look like this

  sub GET_LAYERS { PerlIO​::get_layers($_[0]) }

just like all the rest of the methods there. (PerlIO would have to be
require'd of course.)

-- David

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2011

From @Leont

On Sat, Dec 3, 2011 at 4​:01 AM, David Golden <perlbug-followup@​perl.org> wrote​:

Tied filehandles have BINMODE to modify layers on filehandle,
but no corresponding interface to query the layers already on the
filehandle.

Tied filehandles should support a GET_LAYERS method that
PerlIO​::get_layers would then use to retrieve layers from
tied filehandles.

This change to core would also require updating Tie​::Handle
and Tie​::StdHandle accordingly.

If you ask me, tied filehandles need to *be* a PerlIO layer, instead
of delegating like this. I don't think that'd be possible with the
current PerlIO though…

Leon

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2011

From @Leont

On Sat, Dec 3, 2011 at 4​:30 AM, David Golden <xdaveg@​gmail.com> wrote​:

just like all the rest of the methods there.  (PerlIO would have to be
require'd of course.)

Technically speaking it doesn't. PerlIO​::get_layers is one of those
always subs that's always around. Loading PerlIO is only useful for
loading layers in advance (which is only useful for preforking
purposes AFAIK). Possibly this should be changed.

Leon

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2011

From @xdg

On Sat, Dec 3, 2011 at 7​:32 AM, Leon Timmermans <fawaka@​gmail.com> wrote​:

On Sat, Dec 3, 2011 at 4​:30 AM, David Golden <xdaveg@​gmail.com> wrote​:

just like all the rest of the methods there.  (PerlIO would have to be
require'd of course.)

Technically speaking it doesn't. PerlIO​::get_layers is one of those
always subs that's always around.

Ah. It's not documented to indicate that.

-- David

@p5pRT
Copy link
Author

p5pRT commented Dec 3, 2011

From @Leont

On Sat, Dec 3, 2011 at 3​:48 PM, David Golden <xdaveg@​gmail.com> wrote​:

Ah. It's not documented to indicate that.

-- David

Which is a good reason not to make any such assumption in a non-core module ;-)

Leon

@p5pRT
Copy link
Author

p5pRT commented Dec 4, 2011

From @davidnicol

Cold the requested feature be implemented by addding a tied check to
PerlIO​::get_layers and when tied calling the method on the tie object, plus
documentation of this development in PerlIO and Tie documentation? A tied
handle that does not provide the method could return the tie class as the
layer name, or something like that.

@p5pRT
Copy link
Author

p5pRT commented Dec 4, 2011

From @xdg

On Sat, Dec 3, 2011 at 11​:53 PM, David Nicol <davidnicol@​gmail.com> wrote​:

Cold the requested feature be implemented by addding a tied check  to
PerlIO​::get_layers and when tied calling the method on the tie object, plus
documentation of this development in PerlIO and Tie documentation?

There's no guarantee that the underlying object is a blessed globref.
Nor would that be the right behavior for all tied handles that are
blessed globrefs -- the point of the tie might be exactly to do
something obscure with layers and hide that from the outside world.
Crazy, but not farfetched example​: tie STDOUT so that binmode "​:utf8"
called on the handle gets transparently upgraded to binmode
"​:encoding(UTF-8)". That would give strict UTF8 checks globally
without having to change all lot of code that currently calls
binmode("​:utf8"). Thus a call to get_layers should translate
"​:encoding(UTF-8)" back to "​:utf8".

Querying an underlying blessed globref might be a reasonable fallback,
though, if GET_LAYERS is not provided.

A tied
handle that does not provide the method could return the tie class as the
layer name, or something like that.

That's a bad idea, because you can't call binmode() on that. The goal
is to get something that can roundtrip between get_layers and binmode.
Anything else makes the challenges of tied handles worse, because you
have to screen output of get_layers for validity before applying it
via binmode.

For example, in Capture​::Tiny (where I discovered this issue), I need
to query layers on a filehandle (which might be tied) and then
replicate those layers on another handle used for capturing output.
Test​::Builder does that as well for delivering test output (even on
code that hijacks STDOUT/STDERR). Returning the class name from
get_layers would break those.

-- David

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants