Can one use local to temporarily close STDERR?

K

kj

I would like to know whether it is possible to use localization to
*temporarily* close a global handle, e.g. STDERR. The following
doesn't work (all three messages appear on the screen):

warn "before closing\n";
{
local *STDERR;
# close STDERR;
warn "should be closed\n";
}
warn "still here\n";

If I explicitly close STDERR right after the local statement, then
only the first message gets printed.

Of course, I can achieve the desired effect (namely, selectively
silencing the second message) if I explicitly save and later restore
STDERR:

use Fatal qw( open close );
warn "before closing\n";
{
open my $save, '>&', *STDERR;
close STDERR;
warn "should be closed\n";
open STDERR, '>&', $save;
}
warn "still here\n";

....but I'm curious if there's a way to achieve the same effect without
doing this.

Thanks!

kj
 
A

attn.steven.kuo

kj said:
I would like to know whether it is possible to use localization to
*temporarily* close a global handle, e.g. STDERR. The following
doesn't work (all three messages appear on the screen):

warn "before closing\n";
{
local *STDERR;
# close STDERR;
warn "should be closed\n";
}
warn "still here\n";

If I explicitly close STDERR right after the local statement, then
only the first message gets printed.

Of course, I can achieve the desired effect (namely, selectively
silencing the second message) if I explicitly save and later restore
STDERR:

(snipped)


Would you be satisfied with using a
pseudo signal handler?

warn "once";

{
local $SIG{__WARN__} = sub {};
warn "twice";
}

warn "thrice";
 
B

Brian McCauley

kj said:
I would like to know whether it is possible to use localization to
*temporarily* close a global handle, e.g. STDERR. The following
doesn't work (all three messages appear on the screen):

warn "before closing\n";
{
local *STDERR;
# close STDERR;
warn "should be closed\n";
}
warn "still here\n";

If I explicitly close STDERR right after the local statement, then
only the first message gets printed.

This behaviour has changed a few times in recent Perls.

For example, in 5.8.7 the explict close makes no difference in the
above code.

Opening to /dev/null on the other hand has the desired effect.

See Perl_write_to_stderr() in util.c where Perl tries to DWIM. If there
is a STDERR handle then it uses it, if not then it falls back on
something else. I've not fully traced what this "something else" is but
I suspect it ends up using file descriptor 2 directly.
 
A

Anno Siegel

Brian McCauley said:
This behaviour has changed a few times in recent Perls.

For example, in 5.8.7 the explict close makes no difference in the
above code.

Opening to /dev/null on the other hand has the desired effect.

See Perl_write_to_stderr() in util.c where Perl tries to DWIM. If there
is a STDERR handle then it uses it, if not then it falls back on
something else. I've not fully traced what this "something else" is but
I suspect it ends up using file descriptor 2 directly.

In any case, STDERR is special. The behavior is quite predictable
with a standard file:

open F, '>', $_ or die "Writing $_: $!" for '/tmp/out';

print F "before closing\n";
{
local *F; # F is no longer an open file handle
close F; # "close() on unopened filehandle F"
print F "should be closed\n"; # "print() on unopened filehandle F"
}
print F "still here\n";

The print() inside the block doesn't produce output, with or without the
close(), the other two do. That's what I would expect.

Anno
 
B

Brian McCauley

Anno said:
In any case, STDERR is special.

In what way (that is relevant to this discussion)? IIRC the main
special feature of STDERR is that a failed open() does not close the
old handle.
The behavior is quite predictable with a standard file:

open F, '>', $_ or die "Writing $_: $!" for '/tmp/out';

print F "before closing\n";
{
local *F; # F is no longer an open file handle
close F; # "close() on unopened filehandle F"
print F "should be closed\n"; # "print() on unopened filehandle F"
}
print F "still here\n";

The print() inside the block doesn't produce output, with or without the
close(), the other two do. That's what I would expect.

That's what I would expect too. It's also exactly the same as I see on
5.8.7 using STDERR in place of F.
 

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

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top