PATCH: Mark result stream with FD_CLOEXEC
Mark Mitchell
mark at codesourcery.com
Mon Nov 24 23:02:20 UTC 2003
This patch makes the file opened for writing to the results stream
have the FD_CLOEXEC flag set. That prevents child processes from
having an open file descriptor that they (a) do not need, and (b)
should not use.
--
Mark Mitchell
CodeSourcery, LLC
mark at codesourcery.com
2003-11-24 Mark Mitchell <mark at codesourcery.com>
* qm/common.py (fnctl): Import it.
(close_file_on_exec): New method.
* qm/executable.py (qm.common): Import it.
(Executable.Run): Use close_file_on_exec.
(Executable._MakeCloseOnExec): Remove.
(RedirectedExecutable._CreatePipe): Use close_file_on_exec.
* qm/test/file_result_stream.py (qm.common): Import it.
(FileResultStream.__init__): Use close_file_on_exec.
Index: qm/common.py
===================================================================
RCS file: /home/qm/Repository/qm/qm/common.py,v
retrieving revision 1.78
diff -c -5 -p -r1.78 common.py
*** qm/common.py 24 Nov 2003 00:52:57 -0000 1.78
--- qm/common.py 24 Nov 2003 22:59:03 -0000
*************** import string
*** 37,47 ****
import sys
import tempfile
import time
import traceback
import types
!
########################################################################
# program name
########################################################################
program_name = None
--- 37,49 ----
import sys
import tempfile
import time
import traceback
import types
! if sys.platform != "win32":
! import fcntl
!
########################################################################
# program name
########################################################################
program_name = None
*************** def open_temporary_file():
*** 536,545 ****
--- 538,567 ----
Like 'open_temporary_file_fd', except that the second element of the
return value is a file object."""
file_name, fd = open_temporary_file_fd()
return (file_name, os.fdopen(fd, "w+b"))
+
+
+ def close_file_on_exec(fd):
+ """Prevent 'fd' from being inherited across 'exec'.
+
+ 'fd' -- A file descriptor, or object providing a 'fileno()'
+ method.
+
+ This function has no effect on Windows."""
+
+ if sys.platform != "win32":
+ flags = fcntl.fcntl(fd, fcntl.F_GETFD)
+ try:
+ flags |= fcntl.FD_CLOEXEC
+ except AttributeError:
+ # The Python 2.2 RPM shipped with Red Hat Linux 7.3 does
+ # not define FD_CLOEXEC. Fortunately, FD_CLOEXEC is 1 on
+ # every UNIX system.
+ flags |= 1
+ fcntl.fcntl(fd, fcntl.F_SETFD, flags)
def copy(object):
"""Make a best-effort attempt to copy 'object'.
Index: qm/executable.py
===================================================================
RCS file: /home/qm/Repository/qm/qm/executable.py,v
retrieving revision 1.21
diff -c -5 -p -r1.21 executable.py
*** qm/executable.py 26 Sep 2003 19:55:35 -0000 1.21
--- qm/executable.py 24 Nov 2003 22:59:03 -0000
***************
*** 14,23 ****
--- 14,24 ----
########################################################################
# Imports
#######################################################################
import os
+ import qm.common
import signal
import string
import sys
import time
*************** class Executable(object):
*** 221,231 ****
# it to the parent.
if sys.platform != "win32":
exception_pipe = os.pipe()
# Mark the write end as close-on-exec so that the file
# descriptor is not passed on to the child.
! self._MakeCloseOnExec(exception_pipe[1])
else:
exception_pipe = None
# Start the program.
child = self.Spawn(arguments, environment, dir, path, exception_pipe)
--- 222,232 ----
# it to the parent.
if sys.platform != "win32":
exception_pipe = os.pipe()
# Mark the write end as close-on-exec so that the file
# descriptor is not passed on to the child.
! qm.common.close_file_on_exec(exception_pipe[1])
else:
exception_pipe = None
# Start the program.
child = self.Spawn(arguments, environment, dir, path, exception_pipe)
*************** class Executable(object):
*** 321,351 ****
the value returned is the process handle.)"""
return self.__child
- def _MakeCloseOnExec(self, fd):
- """Prevent 'fd' from being inherited across 'exec'.
-
- 'fd' -- A file descriptor, or object providing a 'fileno()'
- method.
-
- UNIX only."""
-
- assert sys.platform != "win32"
-
- flags = fcntl.fcntl(fd, fcntl.F_GETFD)
- try:
- flags |= fcntl.FD_CLOEXEC
- except AttributeError:
- # The Python 2.2 RPM shipped with Red Hat Linux 7.3 does
- # not define FD_CLOEXEC. Fortunately, FD_CLOEXEC is 1 on
- # every UNIX system.
- flags |= 1
- fcntl.fcntl(fd, fcntl.F_SETFD, flags)
-
-
def __CreateCommandLine(self, arguments):
"""Return a string giving the process command line.
arguments -- A sequence of arguments (including argv[0])
indicating the command to be run.
--- 322,331 ----
*************** class RedirectedExecutable(TimeoutExecut
*** 886,896 ****
r, w = win32pipe.CreatePipe(sa, 0)
return [r, w]
else:
pipe = os.pipe()
for fd in pipe:
! self._MakeCloseOnExec(fd)
return pipe
def __CallUntilNone(self, f, attribute):
"""Call 'f' until 'self.attribute' is 'None'.
--- 866,876 ----
r, w = win32pipe.CreatePipe(sa, 0)
return [r, w]
else:
pipe = os.pipe()
for fd in pipe:
! qm.common.close_file_on_exec(fd)
return pipe
def __CallUntilNone(self, f, attribute):
"""Call 'f' until 'self.attribute' is 'None'.
Index: qm/test/file_result_stream.py
===================================================================
RCS file: /home/qm/Repository/qm/qm/test/file_result_stream.py,v
retrieving revision 1.4
diff -c -5 -p -r1.4 file_result_stream.py
*** qm/test/file_result_stream.py 15 Aug 2003 09:05:23 -0000 1.4
--- qm/test/file_result_stream.py 24 Nov 2003 22:59:03 -0000
***************
*** 13,22 ****
--- 13,23 ----
########################################################################
# Imports
########################################################################
+ import qm.common
import qm.fields
from qm.test.result_stream import ResultStream
import sys
########################################################################
*************** class FileResultStream(ResultStream):
*** 63,72 ****
--- 64,76 ----
if self._is_binary_file:
mode = "wb"
else:
mode = "w"
self.file = open(self.filename, mode, 0)
+ # Child processes do not need to write to the results
+ # file.
+ qm.common.close_file_on_exec(self.file)
else:
self.file = sys.stdout
More information about the qmtest
mailing list