diff options
author | Nicholas Clark <nick@ccl4.org> | 2008-03-12 12:23:55 +0000 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2008-03-12 12:23:55 +0000 |
commit | 711e8db2defd635d78bc9d3e168dbd0a8a3b89fa (patch) | |
tree | 414b704b85c5547624f20317b801e506c48ac4ea /perlio.c | |
parent | 1d791a44a46c93b2808774b83d9ca1f346372145 (diff) | |
download | perl-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.c | 23 |
1 files changed, 22 insertions, 1 deletions
@@ -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; |