summaryrefslogtreecommitdiff
path: root/perlio.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2008-03-12 12:23:55 +0000
committerNicholas Clark <nick@ccl4.org>2008-03-12 12:23:55 +0000
commit711e8db2defd635d78bc9d3e168dbd0a8a3b89fa (patch)
tree414b704b85c5547624f20317b801e506c48ac4ea /perlio.c
parent1d791a44a46c93b2808774b83d9ca1f346372145 (diff)
downloadperl-711e8db2defd635d78bc9d3e168dbd0a8a3b89fa.tar.gz
We need mutex protection in PerlIOStdio_close() for the duration of
holding our true love file handle open, to stop anything else temporarily using it for a quick dup() fling, and then closing the file handle underneath us. I suspect that the lack of this protection was the cause of the threads free.t and blocks.t failures on OS X on 5.8.x, where usefaststdio is the default, and PerlIO is unable to "invalidate" the FILE *. p4raw-id: //depot/perl@33492
Diffstat (limited to 'perlio.c')
-rw-r--r--perlio.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/perlio.c b/perlio.c
index 6459a69672..a0f96ccfb7 100644
--- a/perlio.c
+++ b/perlio.c
@@ -3156,8 +3156,26 @@ PerlIOStdio_close(pTHX_ PerlIO *f)
result = PerlIO_flush(f);
saveerr = errno;
invalidate = PerlIOStdio_invalidate_fileno(aTHX_ stdio);
- if (!invalidate)
+ if (!invalidate) {
dupfd = PerlLIO_dup(fd);
+#ifdef USE_ITHREADS
+ if (dupfd >= 0) {
+ /* Right. We need a mutex here because for a brief while we
+ will have the situation that fd is actually closed.
+ Hence if a second thread were to get into this block,
+ its dup() would likely return our fd as its dupfd.
+ (after all, it is closed). Then if we get to the dup2()
+ first, we blat the fd back (messing up its temporary as
+ a side effect) only for it to then close its dupfd
+ (== our fd) in its close(dupfd) */
+ MUTEX_LOCK(&PL_perlio_mutex);
+ } else {
+ /* Oh cXap. This isn't going to go well. Not sure if we can
+ recover from here, or if closing this particular FILE *
+ is a good idea now. */
+ }
+#endif
+ }
}
result = PerlSIO_fclose(stdio);
/* We treat error from stdio as success if we invalidated
@@ -3173,6 +3191,9 @@ PerlIOStdio_close(pTHX_ PerlIO *f)
#endif
if (dupfd >= 0) {
PerlLIO_dup2(dupfd,fd);
+#ifdef USE_ITHREADS
+ MUTEX_UNLOCK(&PL_perlio_mutex);
+#endif
PerlLIO_close(dupfd);
}
return result;