diff Python/import.c @ 52545:2d80c2797501

get_file() no longer leaks a FILE structure. If given a file descriptor, it calls dup() to get a new handle. Then both the FILE object and the fd can be closed. This is important, because otherwise, the leaked FILE object will be closed on process exit, causing assertions on Windows, e.g. in the test_multiprocessing.py regression test.
author Kristján Valur Jónsson <kristjan@ccpgames.com>
date Tue, 31 Mar 2009 17:43:39 +0000
parents 80271ce09a66
children 6259f80dc24d
line wrap: on
line diff
--- a/Python/import.c	Tue Mar 31 16:57:13 2009 +0000
+++ b/Python/import.c	Tue Mar 31 17:43:39 2009 +0000
@@ -3023,13 +3023,21 @@
 		int fd = PyObject_AsFileDescriptor(fob);
 		if (fd == -1)
 			return NULL;
-		/* XXX This will leak a FILE struct. Fix this!!!!
-		   (But it doesn't leak a file descrioptor!) */
+		if (!_PyVerify_fd(fd))
+			goto error;
+		/* the FILE struct gets a new fd, so that it can be closed
+		 * independently of the file descriptor given
+		 */
+		fd = dup(fd);
+		if (fd == -1)
+			goto error;
 		fp = fdopen(fd, mode);
 	}
-	if (fp == NULL)
-		PyErr_SetFromErrno(PyExc_IOError);
-	return fp;
+	if (fp)
+		return fp;
+error:
+	PyErr_SetFromErrno(PyExc_IOError);
+	return NULL;
 }
 
 static PyObject *
@@ -3051,8 +3059,7 @@
 		return NULL;
 	}
 	m = load_compiled_module(name, pathname, fp);
-	if (fob == NULL)
-		fclose(fp);
+	fclose(fp);
 	PyMem_Free(pathname);
 	return m;
 }
@@ -3081,6 +3088,8 @@
 	}
 	m = _PyImport_LoadDynamicModule(name, pathname, fp);
 	PyMem_Free(pathname);
+	if (fp)
+		fclose(fp);
 	return m;
 }
 
@@ -3105,8 +3114,7 @@
 		return NULL;
 	}
 	m = load_source_module(name, pathname, fp);
-	if (fob == NULL)
-		fclose(fp);
+	fclose(fp);
 	return m;
 }
 
@@ -3150,6 +3158,8 @@
 	} 
 	ret = load_module(name, fp, pathname, type, NULL);
 	PyMem_Free(pathname);
+	if (fp)
+		fclose(fp);
 	return ret;
 }