X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=perlio.c;h=7eb7e27c4ed25598b9abc5e23849f974d8a75c07;hb=6ada912ce2ec33f8cd53bfc96056ec8617e4a08e;hp=a0f96ccfb772222b83775018860b0203a47c4188;hpb=711e8db2defd635d78bc9d3e168dbd0a8a3b89fa;p=p5sagit%2Fp5-mst-13.2.git diff --git a/perlio.c b/perlio.c index a0f96cc..7eb7e27 100644 --- a/perlio.c +++ b/perlio.c @@ -1295,7 +1295,7 @@ PerlIORaw_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg, PerlIO_funcs *tab) while (t && (l = *t)) { if (l->tab->Binmode) { /* Has a handler - normal case */ - if ((*l->tab->Binmode)(aTHX_ f) == 0) { + if ((*l->tab->Binmode)(aTHX_ t) == 0) { if (*t == l) { /* Layer still there - move down a layer */ t = PerlIONext(t); @@ -3131,6 +3131,9 @@ PerlIOStdio_close(pTHX_ PerlIO *f) IV result = 0; int saveerr = 0; int dupfd = -1; +#ifdef USE_ITHREADS + dVAR; +#endif #ifdef SOCKS5_VERSION_NAME /* Socks lib overrides close() but stdio isn't linked to that library (though we are) - so we must call close() @@ -3157,19 +3160,30 @@ PerlIOStdio_close(pTHX_ PerlIO *f) saveerr = errno; invalidate = PerlIOStdio_invalidate_fileno(aTHX_ stdio); if (!invalidate) { +#ifdef USE_ITHREADS + MUTEX_LOCK(&PL_perlio_mutex); + /* 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) */ + + /* There is, of course, a race condition, that any other thread + trying to input/output/whatever on this fd will be stuffed + for the duration of this little manoeuvrer. Perhaps we + should hold an IO mutex for the duration of every IO + operation if we know that invalidate doesn't work on this + platform, but that would suck, and could kill performance. + + Except that correctness trumps speed. + Advice from klortho #11912. */ +#endif 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 { + if (dupfd < 0) { + MUTEX_UNLOCK(&PL_perlio_mutex); /* 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. */ @@ -3191,10 +3205,10 @@ PerlIOStdio_close(pTHX_ PerlIO *f) #endif if (dupfd >= 0) { PerlLIO_dup2(dupfd,fd); + PerlLIO_close(dupfd); #ifdef USE_ITHREADS - MUTEX_UNLOCK(&PL_perlio_mutex); + MUTEX_UNLOCK(&PL_perlio_mutex); #endif - PerlLIO_close(dupfd); } return result; }