From: Ilya Zakharevich on
perl -wle "close STDERR; open F, q(>), q(/dev/tty) or print 11;
print fileno F; warn 22; print STDERR 33; print $x+77"

Try to guess the output (use /dev/con on DOSISH, ' otherwise). Solution below:

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

perl -wle "close STDERR; open F, q(>), q(/dev/tty) or print 11;
print fileno F; warn 22; print STDERR 33; print $x+77"
Name "main::x" used only once: possible typo at -e line 1.
2
22 at -e line 1.
print() on closed filehandle STDERR at -e line 1.
Use of uninitialized value in addition (+) at -e line 1.
77

=======================================================

Of course, 2=`fileno F' is output, as well as 77. And 33 is not.

However, `warn 22' IS output, as well as the warning for `undefined $x'.

Well, at least it was not what I expected... Did anybody succeed?
Which experiences of yours helped you to guess it?

Thanks,
Ilya
From: Ben Morrow on

Quoth Ilya Zakharevich <nospam-abuse(a)ilyaz.org>:
>
> perl -wle "close STDERR; open F, q(>), q(/dev/tty) or print 11;
> print fileno F; warn 22; print STDERR 33; print $x+77"
> Name "main::x" used only once: possible typo at -e line 1.
> 2
> 22 at -e line 1.
> print() on closed filehandle STDERR at -e line 1.
> Use of uninitialized value in addition (+) at -e line 1.
> 77
>
> =======================================================
>
> Of course, 2=`fileno F' is output, as well as 77. And 33 is not.
>
> However, `warn 22' IS output, as well as the warning for `undefined $x'.
>
> Well, at least it was not what I expected... Did anybody succeed?
> Which experiences of yours helped you to guess it?

open(2) is documented as opening the lowest-numbered currently-closed
file descriptor. If you close STDERR, and thus close fd 2, then the
next-opened file handle will be associated with fd 2. If (the
Perl-level) STDERR is currently closed, warn will write its output to
(the C-level) stderr, which means fd 2.

As a rule you should never close STD{IN,OUT,ERR}. If you must, reopen
them to or from File::Spec->devnull.

Ben

From: Ilya Zakharevich on
On 2010-07-05, Ben Morrow <ben(a)morrow.me.uk> wrote:

> If (the Perl-level) STDERR is currently closed, warn will write its
> output to (the C-level) stderr, which means fd 2.

It is THIS behaviour which causes unexpected results. Is it
documented anywhere?

> As a rule you should never close STD{IN,OUT,ERR}. If you must, reopen
> them to or from File::Spec->devnull.

I MUST close them (in all possible combinations) to find bugs in some
UNRELATEDLY obscure ;-) part of perl. And inspecting the output leads to
some deep surprises...

Thanks,
Ilya
From: Ben Morrow on

Quoth Ilya Zakharevich <nospam-abuse(a)ilyaz.org>:
> On 2010-07-05, Ben Morrow <ben(a)morrow.me.uk> wrote:
>
> > If (the Perl-level) STDERR is currently closed, warn will write its
> > output to (the C-level) stderr, which means fd 2.
>
> It is THIS behaviour which causes unexpected results. Is it
> documented anywhere?

I don't know. I don't think so.

> > As a rule you should never close STD{IN,OUT,ERR}. If you must, reopen
> > them to or from File::Spec->devnull.
>
> I MUST close them (in all possible combinations) to find bugs in some
> UNRELATEDLY obscure ;-) part of perl. And inspecting the output leads to
> some deep surprises...

I see.

Ben

From: Ilya Zakharevich on
On 2010-07-05, Ben Morrow <ben(a)morrow.me.uk> wrote:
>> > If (the Perl-level) STDERR is currently closed, warn will write its
>> > output to (the C-level) stderr, which means fd 2.
>>
>> It is THIS behaviour which causes unexpected results. Is it
>> documented anywhere?

> I don't know. I don't think so.

Which does not make the behaviour less puzzling...

[ I note that I have seen this behaviour explicitly mentioned on p5p
in 90s. But at that time I did not realize how puzzling this
behaviour may be. ]

BTW, is there any backdoor way to redirect STDERR to some other fd
than 2?

Thanks again,
Ilya