]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
#1663329: add os.closerange() to close a range of fds,
authorGeorg Brandl <georg@python.org>
Sat, 19 Jan 2008 20:22:13 +0000 (20:22 +0000)
committerGeorg Brandl <georg@python.org>
Sat, 19 Jan 2008 20:22:13 +0000 (20:22 +0000)
ignoring errors, and use this in subprocess to speed up
subprocess creation in close_fds mode. Patch by Mike Klaas.

Doc/library/os.rst
Lib/subprocess.py
Lib/test/test_os.py
Misc/NEWS
Modules/posixmodule.c

index b39ec1bc6b97ca92ec93db5953c7f8989235d417..ff37d10f1d58c501b5ec856e908761efa26cc62b 100644 (file)
@@ -481,6 +481,20 @@ by file descriptors.
       :func:`fdopen`, use its :meth:`close` method.
 
 
+.. function:: closerange(fd_low, fd_high)
+
+   Close all file descriptors from *fd_low* (inclusive) to *fd_high* (exclusive),
+   ignoring errors. Availability: Macintosh, Unix, Windows. Equivalent to::
+
+      for fd in xrange(fd_low, fd_high):
+          try:
+              os.close(fd)
+          except OSError:
+              pass
+
+   .. versionadded:: 2.6
+
+
 .. function:: dup(fd)
 
    Return a duplicate of file descriptor *fd*. Availability: Macintosh, Unix,
index ca9489e67d90ef65a7837f0bb9a5a73f281f4e3e..29c25bcd3aa70d07b50d10653dc190ba58569608 100644 (file)
@@ -965,13 +965,8 @@ class Popen(object):
 
 
         def _close_fds(self, but):
-            for i in xrange(3, MAXFD):
-                if i == but:
-                    continue
-                try:
-                    os.close(i)
-                except:
-                    pass
+            os.closerange(3, but)
+            os.closerange(but + 1, MAXFD)
 
 
         def _execute_child(self, args, executable, preexec_fn, close_fds,
index 52fdd8a4df2a8c36706b02bb616bac8682c0e2ba..a6fe40e83093761fe37c748bb41a22eeaf764559 100644 (file)
@@ -23,6 +23,12 @@ class FileTests(unittest.TestCase):
         os.close(f)
         self.assert_(os.access(test_support.TESTFN, os.W_OK))
 
+    def test_closerange(self):
+        f = os.open(test_support.TESTFN, os.O_CREAT|os.O_RDWR)
+        # close a fd that is open, and one that isn't
+        os.closerange(f, f+2)
+        self.assertRaises(OSError, os.write, f, "a")
+
 
 class TemporaryFileTests(unittest.TestCase):
     def setUp(self):
index fdf1e860a0e6b9269ff25240af0ab3078151cfca..f7c7aac8e97e8251461bc44f983cce3bae2bde96 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -1019,6 +1019,9 @@ Library
 Extension Modules
 -----------------
 
+- Patch #1663329: added ``os.closerange()`` function to quickly close a range
+  of file descriptors without considering errors.
+
 - Patch 976880: ``mmap`` objects now have an ``rfind`` method that
   works as expected.  ``mmap.find`` also takes an optional ``end``
   parameter.
index 696df0dca47f36e2be44d011ae73977c8a5b06a3..00387032a35d319b32af8f5fa7c069e7b4839343 100644 (file)
@@ -6156,6 +6156,24 @@ posix_close(PyObject *self, PyObject *args)
 }
 
 
+PyDoc_STRVAR(posix_closerange__doc__, 
+"closerange(fd_low, fd_high)\n\n\
+Closes all file descriptors in [fd_low, fd_high), ignoring errors.");
+
+static PyObject *
+posix_closerange(PyObject *self, PyObject *args)
+{
+       int fd_from, fd_to, i;
+       if (!PyArg_ParseTuple(args, "ii:closerange", &fd_from, &fd_to))
+               return NULL;
+       Py_BEGIN_ALLOW_THREADS
+       for (i = fd_from; i < fd_to; i++)
+               close(i);
+       Py_END_ALLOW_THREADS
+       Py_RETURN_NONE;
+}
+
+
 PyDoc_STRVAR(posix_dup__doc__,
 "dup(fd) -> fd2\n\n\
 Return a duplicate of a file descriptor.");
@@ -8451,6 +8469,7 @@ static PyMethodDef posix_methods[] = {
 #endif /* HAVE_TCSETPGRP */
        {"open",        posix_open, METH_VARARGS, posix_open__doc__},
        {"close",       posix_close, METH_VARARGS, posix_close__doc__},
+       {"closerange",  posix_closerange, METH_VARARGS, posix_closerange__doc__},
        {"dup",         posix_dup, METH_VARARGS, posix_dup__doc__},
        {"dup2",        posix_dup2, METH_VARARGS, posix_dup2__doc__},
        {"lseek",       posix_lseek, METH_VARARGS, posix_lseek__doc__},