[PATCH] Mark fd's close-on-exec in qm.executable.
Nathaniel Smith
njs at pobox.com
Thu Aug 14 08:17:33 UTC 2003
This patch marks all pipe fd's close-on-exec in
qm.executable.RedirectedExecutable.
-- Nathaniel
--
"If you can explain how you do something, then you're very very bad at it."
-- John Hopfield
-------------- next part --------------
diff -urN --exclude='*~' --exclude='.*' --exclude=CVS --exclude='*.pyo' --exclude='*.pyc' --exclude=build --exclude=GNUmakefile --exclude=config.log --exclude=config.status --exclude=config.cache --exclude=qmtest --exclude=qm.spec --exclude='*.html' --exclude='*.dtd' --exclude=CATALOG --exclude=thread_target --exclude=process_target qm-clean/ChangeLog qm-close-fds/ChangeLog
--- qm-clean/ChangeLog 2003-08-14 01:12:49.000000000 -0700
+++ qm-close-fds/ChangeLog 2003-08-14 00:59:25.000000000 -0700
@@ -1,3 +1,11 @@
+2003-08-14 Nathaniel Smith <njs at codesourcery.com>
+
+ * qm/executable.py (Executable._MakeCloseOnExec): New function.
+ (Executable.Run): Use it.
+ (RedirectedExecutable._CreatePipe): Use it; document that fds
+ will be closed on exec. Add dup logic; document that returned
+ fds will always be >= 3.
+
2003-08-13 Nathaniel Smith <njs at codesourcery.com>
* qm/executable.py (Executable): Typo in docstring.
diff -urN --exclude='*~' --exclude='.*' --exclude=CVS --exclude='*.pyo' --exclude='*.pyc' --exclude=build --exclude=GNUmakefile --exclude=config.log --exclude=config.status --exclude=config.cache --exclude=qmtest --exclude=qm.spec --exclude='*.html' --exclude='*.dtd' --exclude=CATALOG --exclude=thread_target --exclude=process_target qm-clean/qm/executable.py qm-close-fds/qm/executable.py
--- qm-clean/qm/executable.py 2003-08-14 01:12:49.000000000 -0700
+++ qm-close-fds/qm/executable.py 2003-08-14 01:15:10.000000000 -0700
@@ -232,9 +232,7 @@
exception_pipe = os.pipe()
# Mark the write end as close-on-exec so that the file
# descriptor is not passed on to the child.
- fd = exception_pipe[1]
- fcntl.fcntl(fd, fcntl.F_SETFD,
- fcntl.fcntl(fd, fcntl.F_GETFD) | fcntl.FD_CLOEXEC)
+ self._MakeCloseOnExec(exception_pipe[1])
else:
exception_pipe = None
@@ -324,6 +322,17 @@
return self.__child
+ def _MakeCloseOnExec(self, fd):
+ """Modifies 'fd' to not be inherited across 'exec'.
+
+ UNIX only."""
+
+ assert sys.platform != "win32"
+
+ old_flags = fcntl.fcntl(fd, fcntl.F_GETFD)
+ fcntl.fcntl(fd, fcntl.F_SETFD, old_flags | fcntl.FD_CLOEXEC)
+
+
def __CreateCommandLine(self, arguments):
"""Return a string giving the process command line.
@@ -772,7 +781,8 @@
returns -- A tuple (under UNIX) or list (under Windows)
consisting of the file descriptors (UNIX) or handles (Windows)
for the read end and write end of a new pipe. The pipe is
- inheritable by child processes."""
+ inheritable by child processes. On UNIX the fds will always be
+ >= 3 and in close-on-exec mode."""
if sys.platform == "win32":
# Create a security descriptor so that we can mark the handles
@@ -785,8 +795,20 @@
r, w = win32pipe.CreatePipe(sa, 0)
return [r, w]
else:
- return os.pipe()
-
+ pipe = os.pipe()
+ for fd in pipe:
+ # Push the fd up above 2, to make sure it won't conflict
+ # with stdin/stdout/stderr.
+ closable = []
+ while fd <= 2:
+ closable.append(fd)
+ fd = os.dup(fd)
+ for old in closable:
+ os.close(old)
+ # And make it close-on-exec.
+ self._MakeCloseOnExec(fd)
+ return pipe
+
def __CallUntilNone(self, f, attribute):
"""Call 'f' until 'self.attribute' is 'None'.
Binary files qm-clean/results.qmr and qm-close-fds/results.qmr differ
More information about the qmtest
mailing list