summaryrefslogtreecommitdiff
path: root/perlio.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2007-11-05 13:58:52 +0000
committerNicholas Clark <nick@ccl4.org>2007-11-05 13:58:52 +0000
commitbbbc33d002fb16005d670814239b18d82b3e6229 (patch)
tree1e452e6c718b3ac5e3ae133f9485a895c3c22fa3 /perlio.c
parenta396bf53e008922a27c700e1af53f555c39457a7 (diff)
downloadperl-bbbc33d002fb16005d670814239b18d82b3e6229.tar.gz
As reported in bug #46207, change 30633 to PerlIO_exportFILE() and
PerlIO_releaseFILE() to manage the reference counts of fds correctly has the side effect of making some XS modules "leak" descriptors. This is because the typemap calls PerlIO_findFILE(), which sometimes (but not always) calls PerlIO_exportFILE(). To be consistent, PerlIO_fildFILE() needs to either always give you a reference, or always not give you a reference. It seems better to do the latter as the call to PerlIO_exportFILE() is only an implementation detail, so arrange for it to immediately free up the reference that PerlIO_exportFILE() created. p4raw-id: //depot/perl@32224
Diffstat (limited to 'perlio.c')
-rw-r--r--perlio.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/perlio.c b/perlio.c
index c0e73274bc..966894c5d0 100644
--- a/perlio.c
+++ b/perlio.c
@@ -3578,6 +3578,7 @@ FILE *
PerlIO_findFILE(PerlIO *f)
{
PerlIOl *l = *f;
+ FILE *stdio;
while (l) {
if (l->tab == &PerlIO_stdio) {
PerlIOStdio *s = PerlIOSelf(&l, PerlIOStdio);
@@ -3586,7 +3587,19 @@ PerlIO_findFILE(PerlIO *f)
l = *PerlIONext(&l);
}
/* Uses fallback "mode" via PerlIO_modestr() in PerlIO_exportFILE */
- return PerlIO_exportFILE(f, NULL);
+ /* However, we're not really exporting a FILE * to someone else (who
+ becomes responsible for closing it, or calling PerlIO_releaseFILE())
+ So we need to undo its refernce count increase on the underlying file
+ descriptor. We have to do this, because if the loop above returns you
+ the FILE *, then *it* didn't increase any reference count. So there's
+ only one way to be consistent. */
+ stdio = PerlIO_exportFILE(f, NULL);
+ if (stdio) {
+ const int fd = fileno(stdio);
+ if (fd >= 0)
+ PerlIOUnix_refcnt_dec(fd);
+ }
+ return stdio;
}
/* Use this to reverse PerlIO_exportFILE calls. */