diff options
author | Nicholas Clark <nick@ccl4.org> | 2007-11-05 13:58:52 +0000 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2007-11-05 13:58:52 +0000 |
commit | bbbc33d002fb16005d670814239b18d82b3e6229 (patch) | |
tree | 1e452e6c718b3ac5e3ae133f9485a895c3c22fa3 /perlio.c | |
parent | a396bf53e008922a27c700e1af53f555c39457a7 (diff) | |
download | perl-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.c | 15 |
1 files changed, 14 insertions, 1 deletions
@@ -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. */ |