How to local-ly close a handle?

K

kj

One would think that one of the few good uses left for the keyword
"local" would be to "local-ly" close an open handle, like this:

my $status;
{
local *STDERR;
$status = system 'crazystuff';
}

die "can't do crazystuff!: $?" unless $status == 0;

But NOOOOO! The above fails to silence STDERR. If one attempts
a "close STDERR" after the "plain" local statement shown above,
one gets an error about attempting to close an unopened handle.
If then one tries this:

my $status;
{
local *STDERR = *STDERR; close STDERR;
$status = system 'crazystuff';
}

die "can't do crazystuff!: $?" unless $status == 0;

....then STDERR *is* finally silenced, but it *remains* silenced outside
of the block (e.g. the message from the die statement doesn't show);
i.e. the closing is not localized.

I know of ways to temporarily silence STDERR that actually work,
but none of them begins to approach the simplicity of any of the
examples above. Any suggestions?

TIA!

kj
 
B

Ben Morrow

Quoth "Ferry Bolhar said:
kj:


Yes. How about:

system 'crazystuff 2>/dev/null';

Localizing STDERR with whatever has no impact on child processes,
because the parent process' STDERR (which the child inherits) still
remains open.

This is mostly just being picky :), but that would be better as

Localizing STDERR has no impact on child processes, because the parent
process' file-descriptor 2 (which the child inherits) remains open.

The point being that the confusion here is between Perl's STDERR and
perl's fd #2.
It will have an impact when you do a "print STDERR"
or somewhat similar, but it's meaningful with Perl commands only.

And although you can localize a typeglob (and its associated IO handle),
you can't localize a close! So if you close a file (as you did with "close
STDERR"), the file will remain closed, even when leaving the block!

The fd you closed will remain closed, but the Perl filehandle will
revert to pointing to its old fd, and thus will be open again. :)

Ben
 
B

Ben Morrow

Quoth "Ferry Bolhar said:
Ben Morrow:

....unless you've closed the old fd as well in the meantime.
So, this contradicts what you said above, doesn't it?

The OP's example was

local *STDERR = *STDERR;

so in this case old fd == new fd, and obviously closing one closes the
other.

Ben
 
M

Michele Dondi

One would think that one of the few good uses left for the keyword
"local" would be to "local-ly" close an open handle, like this:

"local" is an adjective, "locally" is an adverb. Perl (up to) 5 does
not really support adverbs, while they will be a pervasive concept in
Perl 6. I'm not suggesting you to wait till the beast is up and
running, just pointing it out FYI.


Michele
 

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,774
Messages
2,569,596
Members
45,142
Latest member
arinsharma
Top