summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2008-10-26 18:37:35 +0000
committerNicholas Clark <nick@ccl4.org>2008-10-26 18:37:35 +0000
commitd8723f436e1dd34e1353ad7e3538918033d31d15 (patch)
treef5ae932059bc4b2a9fe577ac05d567a242deeb4a
parente187df3b2e2d86a597bd5d2d631175f15fd61d9d (diff)
downloadperl-d8723f436e1dd34e1353ad7e3538918033d31d15.tar.gz
Cope with brain damage in PerlIO::via, which will let you fclose() the
same FILE * twice, thanks to it calling out to Perl space inside the close call tree, with the underlying PerlIO * already closed, but not unlinked. p4raw-id: //depot/perl@34596
-rw-r--r--perlio.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/perlio.c b/perlio.c
index 466dd13ee0..faf814718f 100644
--- a/perlio.c
+++ b/perlio.c
@@ -3144,8 +3144,15 @@ PerlIOStdio_close(pTHX_ PerlIO *f)
if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *) &optval, &optlen) == 0)
invalidate = 1;
#endif
- if (PerlIOUnix_refcnt_dec(fd) > 0) /* File descriptor still in use */
+ /* Test for -1, as *BSD stdio (at least) on fclose sets the FILE* such
+ that a subsequent fileno() on it returns -1. Don't want to croak()
+ from within PerlIOUnix_refcnt_dec() if some buggy caller code is
+ trying to close an already closed handle which somehow it still has
+ a reference to. (via.xs, I'm looking at you). */
+ if (fd != -1 && PerlIOUnix_refcnt_dec(fd) > 0) {
+ /* File descriptor still in use */
invalidate = 1;
+ }
if (invalidate) {
/* For STD* handles, don't close stdio, since we shared the FILE *, too. */
if (stdio == stdin) /* Some stdios are buggy fflush-ing inputs */