PEP 446: update after Guido's review

This commit is contained in:
Victor Stinner 2013-08-27 00:01:04 +02:00
parent 091eb3e838
commit fbeac3a6e1
1 changed files with 24 additions and 17 deletions

View File

@ -24,6 +24,10 @@ fixes also a race condition in multi-threaded applications on operating
systems supporting atomic flags to create non-inheritable file systems supporting atomic flags to create non-inheritable file
descriptors. descriptors.
We are aware of the code breakage this is likely to cause, and doing it
anyway for the good of mankind. (Details in the section "Backward
Compatibility" below.)
Rationale Rationale
========= =========
@ -79,6 +83,11 @@ the *dwFlags* field of the ``STARTUPINFO`` structure and the
``TRUE``. So when at least one standard stream is replaced, all ``TRUE``. So when at least one standard stream is replaced, all
inheritable handles are inherited by the child process. inheritable handles are inherited by the child process.
The default value of the *close_fds* parameter of ``subprocess`` process
is ``True`` (``bInheritHandles=FALSE``) if *stdin*, *stdout* and
*stderr* parameters are ``None``, ``False`` (``bInheritHandles=TRUE``)
otherwise.
See also: See also:
* `Handle Inheritance * `Handle Inheritance
@ -430,12 +439,6 @@ MAXFD is the maximum number of file descriptors, even if there are only
few open file descriptors. This maximum can be read using: few open file descriptors. This maximum can be read using:
``os.sysconf("SC_OPEN_MAX")``. ``os.sysconf("SC_OPEN_MAX")``.
There is no portable nor reliable function to close all open file
descriptors between ``fork()`` and ``execv()``. Another thread may
create an inheritable file descriptors while we are closing existing
file descriptors. Holding the CPython GIL reduces the risk of the race
condition.
The operation can be slow if MAXFD is large. For example, on a FreeBSD The operation can be slow if MAXFD is large. For example, on a FreeBSD
buildbot with ``MAXFD=655,000``, the operation took 300 ms: see buildbot with ``MAXFD=655,000``, the operation took 300 ms: see
`issue #11284: slow close file descriptors `issue #11284: slow close file descriptors
@ -445,10 +448,6 @@ On Linux, Python 3.3 gets the list of all open file descriptors from
``/proc/<PID>/fd/``, and so performances depends on the number of open ``/proc/<PID>/fd/``, and so performances depends on the number of open
file descriptors, not on MAXFD. file descriptors, not on MAXFD.
FreeBSD, OpenBSD and Solaris provide a ``closefrom()`` function. It
cannot be used by the ``subprocess`` module when the *pass_fds*
parameter is a non-empty list of file descriptors.
See also: See also:
* `Python issue #1663329 <http://bugs.python.org/issue1663329>`_: * `Python issue #1663329 <http://bugs.python.org/issue1663329>`_:
@ -485,6 +484,8 @@ descriptors non-inheritable by default:
* ``socket.socket.fromfd()`` * ``socket.socket.fromfd()``
* ``socket.socketpair()`` * ``socket.socketpair()``
``os.dup2()`` still creates inheritable by default, see below.
When available, atomic flags are used to make file descriptors When available, atomic flags are used to make file descriptors
non-inheritable. The atomicity is not guaranteed because a fallback is non-inheritable. The atomicity is not guaranteed because a fallback is
required when atomic flags are not available. required when atomic flags are not available.
@ -518,14 +519,20 @@ New methods:
Other Changes Other Changes
------------- -------------
* On UNIX, subprocess makes file descriptors of the *pass_fds* parameter On UNIX, subprocess makes file descriptors of the *pass_fds* parameter
inheritable. The file descriptor is made inheritable in the child inheritable. The file descriptor is made inheritable in the child
process after the ``fork()`` and before ``execv()``, so the inheritable process after the ``fork()`` and before ``execv()``, so the inheritable
flag of file descriptors is unchanged in the parent process. flag of file descriptors is unchanged in the parent process.
* ``os.dup2()`` has a new optional *inheritable* parameter: ``os.dup2()`` has a new optional *inheritable* parameter: ``os.dup2(fd,
``os.dup2(fd, fd2, inheritable=True)``. *fd2* is created inheritable fd2, inheritable=True)``. *fd2* is created inheritable by default, but
by default, but non-inheritable if *inheritable* is ``False``. non-inheritable if *inheritable* is ``False``.
``os.dup2()`` behaves differently than ``os.dup()`` because the most
common use case of ``os.dup2()`` is to replace the file descriptors of
the standard streams: ``stdin`` (``0``), ``stdout`` (``1``) and
``stdout`` (``2``). Standard streams are expected to be inherited by
child processes.
Since Python should only create non-inheritable file descriptors, it is Since Python should only create non-inheritable file descriptors, it is
safe to use subprocess with the *close_fds* parameter set to ``False``. safe to use subprocess with the *close_fds* parameter set to ``False``.