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)); }
In reply to Re^3: reading from a file after a seek isn't working for me
by almut
in thread reading from a file after a seek isn't working for me
by samwyse
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |