can you please explain in detail the need for the explicit close here?
I think it has to do with PerlIO in combination with an implementation peculiarity.
When you compare the straces of both variants, you'll see something like:
# with explicit close
close(1) = 0
open("/tmp/stdout.log", O_RDWR|O_CREAT|O_TRUNC, 0666) = 1
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fff2ba69a30) = -1 ENOTTY (I
+nappropriate ioctl for device)
lseek(1, 0, SEEK_CUR) = 0
fstat(1, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
fcntl(1, F_SETFD, 0) = 0
# without explicit close
open("/tmp/stdout.log", O_RDWR|O_CREAT|O_TRUNC, 0666) = 4
ioctl(4, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fff023c1390) = -1 ENOTTY (I
+nappropriate ioctl for device)
lseek(4, 0, SEEK_CUR) = 0
fstat(4, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
dup2(4, 1) = 1
close(4) = 0
fcntl(1, F_SETFD, 0) = 0
Now, the issue is (I think) that although the dup2 does
create a copy of fd 4 as fd 1 at the system level (and in fact
does also close the old fd 1), it does not copy the PerlIO part,
which is only being handled properly, when the filehandle is being
created directly using Perl's open. For this reason, the
filedescriptor is considered invalid from the PerlIO point of view (—> the "Bad file descriptor" message).
This is checked at the beginning of Perl's read using
PerlIOValid(f)1 (even before doing any read system call).
Don't ask (me), however, why the indirect dup2-technique is being
used in the first place instead of simply closing the filedescriptor
before the open... (Presumably, it did work before the the introduction of PerlIO, and might just not have been adapted appropriately since.)
___
1 see perlio.c:
#define Perl_PerlIO_or_Base(f, callback, base, failure, args) \
if (PerlIOValid(f)) { \
const PerlIO_funcs * const tab = PerlIOBase(f)->tab;\
if (tab && tab->callback) \
return (*tab->callback) args; \
else \
return PerlIOBase_ ## base args; \
} \
else \
SETERRNO(EBADF, SS_IVCHAN); \
return failure
...
SSize_t
Perl_PerlIO_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
{
Perl_PerlIO_or_Base(f, Read, read, -1, (aTHX_ f, vbuf, count));
}
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.