File handle to "in memory" file

F

Frank Seitz

Hi folks,

with

open $fh,'>',\$var

I can connect a file handle $fh with a scalar $var.

How can I find out, given $fh, whether $fh is connected
with a scalar and which scalar it is connected with.

Frank
 
F

Frank Seitz

Ben said:
fileno($fh) will return -1 if $fh is opened like this. There are other
situations where fileno can return -1, but you are not likely to come
across them unless you're messing about with PerlIO layers.

Maybe PerlIO::get_layers($fh) is more reliable. It returns 'scalar'
in this case, as someone told me in the german Perl NG.
This you can't find at all easily.

Thank you very much for your response.

Frank
 
F

Frank Seitz

Christian said:
I don't think there's a solution to that which doesn't entail
delving into the depth of the header files and analyzing the
file handle's glob magic.

It's a pity, because I think I need this.

Frank
 
U

Uri Guttman

FS> It's a pity, because I think I need this.

i would wager a large sum of quatloos that you don't need it. please
post your (imagined :) reasons for needing this. how would you have many
scalar files where you needed to track which var was attached to which
handle? and if you did, a trivial and correct solution would be to
manage a hash of the refs to the vars and the handles (maybe two hashes,
one for each mapping direction). there, simple pure perl and no need for
guts introspection. i still want to know what is your design and
reasoning for needed so many of these and to track them. when i hear
about tracking of handles and files and such i smell XY problems. and my
perl nose is especially acute!

uri
 
F

Frank Seitz

Uri said:
FS> It's a pity, because I think I need this.

i would wager a large sum of quatloos that you don't need it. please
post your (imagined :) reasons for needing this.

I wrote a simple class "StderrCatcher". The constructor
closes STDERR and reopens it as handle to an "in memory" file:

our $Stderr;

sub new {
my $class = shift;

close STDERR;
open STDERR,'>',\$Stderr or die;

return bless \$Stderr,$class;
}

With a call to

sub string {
my $self = shift;
return $$self;
}

I get everything the program has written to STDERR since
object instantiation.

Now the problem: The constructor should close and reopen STDERR
if and only if STDERR is not connected with class variable $Stderr.

It's a class which is used in a persistent runtime environment
(CGI::SpeedyCGI) and knows nothing about the outside world, especially
nothing about the state of the global STDERR.

Frank
 
U

Uri Guttman

FS> Uri Guttman wrote:

FS> I wrote a simple class "StderrCatcher". The constructor
FS> closes STDERR and reopens it as handle to an "in memory" file:

FS> our $Stderr;

no need for out as long as only this module needs to see $Stderr

FS> sub new {
FS> my $class = shift;

FS> close STDERR;
FS> open STDERR,'>',\$Stderr or die;

FS> return bless \$Stderr,$class;
FS> }

FS> With a call to

FS> sub string {
FS> my $self = shift;
FS> return $$self;
FS> }

FS> I get everything the program has written to STDERR since
FS> object instantiation.

and this is important? and you only have one string var but you asked to
find out WHICH var was opened for a handle. we showed you to how to
determine that the handle is attached to a scalar.

FS> Now the problem: The constructor should close and reopen STDERR
FS> if and only if STDERR is not connected with class variable $Stderr.

but how could it be connected to any other variable in your code? you
control it. also your current open does a > which supposed should wipe
out the variable's current data (assuming it acts like > on a file).

if you really need more control use a tied handle (which can be attached
to any object reference including a hash). store in that hash the
reference as well and make a method that accesses it. but i still don't
see the need to know which var is attached to the handle if you only
have one global handle/var.

there are other ways to trap stderr too. assuming you use warn (not
print STDERR) you can use the warning handler in %SIG and then easily
append all warn output to some var or a log file.

FS> It's a class which is used in a persistent runtime environment
FS> (CGI::SpeedyCGI) and knows nothing about the outside world, especially
FS> nothing about the state of the global STDERR.

and now the harder question, why are you keeping a stderr log in ram and
not on disk? when are you going to check it? it will be lost when the
demon restarts.

uri
 
F

Frank Seitz

Uri said:
FS> our $Stderr;

no need for out as long as only this module needs to see $Stderr

Okay, but this is not relevant, I think.

[Class for STDERR redirection]
and this is important? and you only have one string var but you asked to
find out WHICH var was opened for a handle. we showed you to how to
determine that the handle is attached to a scalar.

From the class' point of view someone else could have opend
the filehandle as an in memory file. The class should redirect in this case too.
The suggested test is not sufficient.
but how could it be connected to any other variable in your code? you
control it.

Ideally a class is a piece of code that works properly without
assumptions about the program it is used in.
if you really need more control use a tied handle (which can be attached
to any object reference including a hash). store in that hash the
reference as well and make a method that accesses it. but i still don't
see the need to know which var is attached to the handle if you only
have one global handle/var.

You missed the point. I can't remember the state by myself, because
STDERR may change during program execution (under CGI::SpeedyCGI STDERR is
reopened with every CGI call).
there are other ways to trap stderr too. assuming you use warn (not
print STDERR) you can use the warning handler in %SIG and then easily
append all warn output to some var or a log file.

I know this (in my opinon: ugly) concept. I need to capture
the whole STDERR output.
FS> It's a class which is used in a persistent runtime environment
FS> (CGI::SpeedyCGI) and knows nothing about the outside world, especially
FS> nothing about the state of the global STDERR.

and now the harder question, why are you keeping a stderr log in ram and
not on disk? when are you going to check it? it will be lost when the
demon restarts.

I use the class in (persistent) CGIs. The class captures STDERR during
execution and the program puts the output into the HTTP response at
the appropriate point. It works well. The limitation in Perls
filehandle API is not a real problem for me: I simply close STDERR
unconditionally and accept the consequence that output between
multiple constructor calls is lost.

Frank
 
F

Frank Seitz

Uri said:
FS> Ideally a class is a piece of code that works properly without
FS> assumptions about the program it is used in.

and you assume that if your module is used then it will always do this
stderr thing. make it an option and just do it when enabled. let the top
level code decide whether to enable it or not. checking to see if the
var is used by some other module is silly. what if that module is loaded
after yours and overrides your stuff? you can't predict this so letting
top level code handle the decision and offering this OPTIONAL service is
the best way.

1. A class is not a module and vice versa.
2. A constructor is not called automatically.
FS> You missed the point. I can't remember the state by myself, because
FS> STDERR may change during program execution (under CGI::SpeedyCGI STDERR is
FS> reopened with every CGI call).

blech. you can always retie it later. and tied is easier to detect.

Okay, your are right, a tied object is precisely detectable. This is
what I miss for scalars in the filehandle API. But ties are slow and
I don't like the code very much.
FS> I use the class in (persistent) CGIs. The class captures STDERR during
FS> execution and the program puts the output into the HTTP response at
FS> the appropriate point. It works well. The limitation in Perls
FS> filehandle API is not a real problem for me: I simply close STDERR
FS> unconditionally and accept the consequence that output between
FS> multiple constructor calls is lost.

and that is acceptable vs my suggestions?
Yes.

i think you have painted
yourself into a deep corner. this is definitely an xy problem now. your
bigger problem is solvable without much pain but you have already
chosen a path (and sticking to it) which has much more pain.

No, it's not an xy problem. I asked a concrete question
about Perls filehandle API and I know by myself what I have to conclude from
the (in this case: negative) answer.

Frank
 
U

Uri Guttman

FS> Ideally a class is a piece of code that works properly without
FS> assumptions about the program it is used in.
FS> 1. A class is not a module and vice versa.
FS> 2. A constructor is not called automatically.

please don't teach me perl! :)

FS> You missed the point. I can't remember the state by myself, because
FS> STDERR may change during program execution (under CGI::SpeedyCGI STDERR is
FS> reopened with every CGI call).
FS> Okay, your are right, a tied object is precisely detectable. This is
FS> what I miss for scalars in the filehandle API. But ties are slow and
FS> I don't like the code very much.

agreed they are slow. if you are concerned about speedy reopening
stderr, then why don't you close your string and reopen it each time
too? i still don't see the issue.

FS> No, it's not an xy problem. I asked a concrete question about
FS> Perls filehandle API and I know by myself what I have to conclude
FS> from the (in this case: negative) answer.

well i am sure a better overall solution exists. in fact i know it. but
i can't convince you of that. hence i have to call it an xy problem. not
much more i can do here.

uri
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,733
Messages
2,569,440
Members
44,830
Latest member
ZADIva7383

Latest Threads

Top