PEP 433: change the proposal to sys.setdefaultcloexec(cloexec: bool)
This commit is contained in:
parent
36d505a562
commit
6b8569c21e
394
pep-0433.txt
394
pep-0433.txt
|
@ -13,10 +13,14 @@ Python-Version: 3.4
|
||||||
Abstract
|
Abstract
|
||||||
========
|
========
|
||||||
|
|
||||||
This PEP proposes to add a new optional parameter ``cloexec`` on
|
Add a new optional *cloexec* parameter on functions creating file
|
||||||
functions creating file descriptors in the Python standard library. If
|
descriptors, add different ways to change default values of this
|
||||||
the parameter is ``True``, the close-on-exec flag will be set on the
|
parameter, and add four new functions:
|
||||||
new file descriptor.
|
|
||||||
|
* ``os.get_cloexec(fd)``
|
||||||
|
* ``os.set_cloexec(fd, cloexec=True)``
|
||||||
|
* ``sys.getdefaultcloexec()``
|
||||||
|
* ``sys.setdefaultcloexec(cloexec=True)``
|
||||||
|
|
||||||
|
|
||||||
Rationale
|
Rationale
|
||||||
|
@ -25,38 +29,42 @@ Rationale
|
||||||
A file descriptor has a close-on-exec flag which indicates if the file
|
A file descriptor has a close-on-exec flag which indicates if the file
|
||||||
descriptor will be inherited or not.
|
descriptor will be inherited or not.
|
||||||
|
|
||||||
On UNIX, the file descriptor will be closed on the execution of child processes
|
On UNIX, if the close-on-exec flag is set, the file descriptor is not
|
||||||
if the close-on-exec flag is set, the file descriptor is inherited by child
|
inherited: it will be closed at the execution of child processes;
|
||||||
processes if the flag is cleared.
|
otherwise the file descriptor is inherited by child processes.
|
||||||
|
|
||||||
On Windows, the file descriptor is not inherited if the close-on-exec flag is
|
On Windows, if the close-on-exec flag is set, the file descriptor is not
|
||||||
set, the file descriptor is inherited by child processes if the flag is cleared
|
inherited; the file descriptor is inherited by child processes if the
|
||||||
and if ``CreateProcess()`` is called with the *bInheritHandles* parameter set
|
close-on-exec flag is cleared and if ``CreateProcess()`` is called with
|
||||||
to ``TRUE`` (when ``subprocess.Popen`` is created with ``close_fds=False`` for
|
the *bInheritHandles* parameter set to ``TRUE`` (when
|
||||||
example).
|
``subprocess.Popen`` is created with ``close_fds=False`` for example).
|
||||||
|
Windows does now have "close-on-exec" flag but an inherance flag which
|
||||||
|
is just the opposite value. For example, setting close-on-exec flag set
|
||||||
|
means clearing the ``HANDLE_FLAG_INHERIT`` flag of an handle.
|
||||||
|
|
||||||
|
|
||||||
Status in Python 3.3
|
Status in Python 3.3
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
On UNIX, the subprocess module closes file descriptors greater than 2 by
|
On UNIX, the subprocess module closes file descriptors greater than 2 by
|
||||||
default since Python 3.2 [#subprocess_close]_. All file descriptors created by
|
default since Python 3.2 [#subprocess_close]_. All file descriptors
|
||||||
the parent process are automatically closed in the child process.
|
created by the parent process are automatically closed in the child
|
||||||
|
process.
|
||||||
|
|
||||||
``xmlrpc.server.SimpleXMLRPCServer`` sets the close-on-exec flag of
|
``xmlrpc.server.SimpleXMLRPCServer`` sets the close-on-exec flag of
|
||||||
the listening socket, the parent class ``socketserver.BaseServer``
|
the listening socket, the parent class ``socketserver.TCPServer``
|
||||||
does not set this flag.
|
does not set this flag.
|
||||||
|
|
||||||
There are other cases creating a subprocess or executing a new program
|
There are other cases creating a subprocess or executing a new program
|
||||||
where file descriptors are not closed: functions of the os.spawn*()
|
where file descriptors are not closed: functions of the ``os.spawn*()``
|
||||||
family and third party modules calling ``exec()`` or ``fork()`` +
|
and the ``os.exec*()`` families and third party modules calling
|
||||||
``exec()``. In this case, file descriptors are shared between the
|
``exec()`` or ``fork()`` + ``exec()``. In this case, file descriptors
|
||||||
parent and the child processes which is usually unexpected and causes
|
are shared between the parent and the child processes which is usually
|
||||||
various issues.
|
unexpected and causes various issues.
|
||||||
|
|
||||||
This PEP proposes to continue the work started with the change in the
|
This PEP proposes to continue the work started with the change in the
|
||||||
subprocess, to fix the issue in any code, and not just code using
|
subprocess in Python 3.2, to fix the issue in any code, and not just
|
||||||
subprocess.
|
code using subprocess.
|
||||||
|
|
||||||
|
|
||||||
Inherited file descriptors issues
|
Inherited file descriptors issues
|
||||||
|
@ -66,15 +74,14 @@ Closing the file descriptor in the parent process does not close the
|
||||||
related resource (file, socket, ...) because it is still open in the
|
related resource (file, socket, ...) because it is still open in the
|
||||||
child process.
|
child process.
|
||||||
|
|
||||||
The listening socket of TCPServer is not closed on ``exec()``: the
|
The listening socket of TCPServer is not closed on ``exec()``: the child
|
||||||
child process is able to get connection from new clients; if the
|
process is able to get connection from new clients; if the parent closes
|
||||||
parent closes the listening socket and create a new listening socket
|
the listening socket and create a new listening socket on the same
|
||||||
on the same address, it would get an "address already is used" error.
|
address, it would get an "address already is used" error.
|
||||||
|
|
||||||
Not closing file descriptors can lead to resource exhaustion: even if
|
Not closing file descriptors can lead to resource exhaustion: even if
|
||||||
the parent closes all files, creating a new file descriptor may fail
|
the parent closes all files, creating a new file descriptor may fail
|
||||||
with "too many files" because files are still open in the child
|
with "too many files" because files are still open in the child process.
|
||||||
process.
|
|
||||||
|
|
||||||
See also the following issues:
|
See also the following issues:
|
||||||
|
|
||||||
|
@ -160,20 +167,6 @@ standard library. Third party modules not using the standard library
|
||||||
should be modified to conform to this PEP. The new
|
should be modified to conform to this PEP. The new
|
||||||
``os.set_cloexec()`` function can be used for example.
|
``os.set_cloexec()`` function can be used for example.
|
||||||
|
|
||||||
Impacted functions:
|
|
||||||
|
|
||||||
* ``os.forkpty()``
|
|
||||||
* ``http.server.CGIHTTPRequestHandler.run_cgi()``
|
|
||||||
|
|
||||||
Impacted modules:
|
|
||||||
|
|
||||||
* ``multiprocessing``
|
|
||||||
* ``socketserver``
|
|
||||||
* ``subprocess``
|
|
||||||
* ``tempfile``
|
|
||||||
* ``xmlrpc.server``
|
|
||||||
* Maybe: ``signal``, ``threading``
|
|
||||||
|
|
||||||
XXX Should ``subprocess.Popen`` clear the close-on-exec flag on file
|
XXX Should ``subprocess.Popen`` clear the close-on-exec flag on file
|
||||||
XXX descriptors of the constructor the ``pass_fds`` parameter?
|
XXX descriptors of the constructor the ``pass_fds`` parameter?
|
||||||
|
|
||||||
|
@ -185,78 +178,93 @@ XXX descriptors of the constructor the ``pass_fds`` parameter?
|
||||||
Proposal
|
Proposal
|
||||||
========
|
========
|
||||||
|
|
||||||
This PEP proposes to add a new optional parameter ``cloexec`` on
|
Add a new optional *cloexec* parameter on functions creating file
|
||||||
functions creating file descriptors in the Python standard library. If
|
descriptors and different ways to change default values of this
|
||||||
the parameter is ``True``, the close-on-exec flag will be set on the
|
parameter.
|
||||||
new file descriptor.
|
|
||||||
|
|
||||||
Add a new functions:
|
Add new functions:
|
||||||
|
|
||||||
* ``os.get_cloexec(fd:int) -> bool``: get the
|
* ``os.get_cloexec(fd:int) -> bool``: get the
|
||||||
close-on-exec flag of a file descriptor. Not available on all platforms.
|
close-on-exec flag of a file descriptor. Not available on all
|
||||||
|
platforms.
|
||||||
* ``os.set_cloexec(fd:int, cloexec:bool=True)``: set or clear the
|
* ``os.set_cloexec(fd:int, cloexec:bool=True)``: set or clear the
|
||||||
close-on-exec flag on a file descriptor. Not available on all platforms.
|
close-on-exec flag on a file descriptor. Not available on all
|
||||||
|
platforms.
|
||||||
|
* ``sys.getdefaultcloexec() -> bool``: get the current default value
|
||||||
|
of the *cloexec* parameter
|
||||||
|
* ``sys.setdefaultcloexec(cloexec: bool=True)``: set the default value
|
||||||
|
of the *cloexec* parameter
|
||||||
|
|
||||||
Add a new optional ``cloexec`` parameter to:
|
Add a new optional *cloexec* parameter to:
|
||||||
|
|
||||||
* ``open()``: ``os.fdopen()`` is indirectly modified
|
* ``asyncore.dispatcher.create_socket()``
|
||||||
* ``os.dup()``, ``os.dup2()``
|
* ``io.FileIO``
|
||||||
|
* ``io.open()``
|
||||||
|
* ``open()``
|
||||||
|
* ``os.dup()``
|
||||||
|
* ``os.dup2()``
|
||||||
|
* ``os.fdopen()``
|
||||||
|
* ``os.open()``
|
||||||
|
* ``os.openpty()``
|
||||||
* ``os.pipe()``
|
* ``os.pipe()``
|
||||||
* ``socket.socket()``, ``socket.socketpair()``,
|
* ``select.devpoll()``
|
||||||
``socket.socket.accept()``
|
* ``select.epoll()``
|
||||||
* Maybe also: ``os.open()``, ``os.openpty()``
|
* ``select.kqueue()``
|
||||||
* TODO:
|
* ``socket.socket()``
|
||||||
|
* ``socket.socket.accept()``
|
||||||
|
* ``socket.socket.dup()``
|
||||||
|
* ``socket.socket.fromfd``
|
||||||
|
* ``socket.socketpair()``
|
||||||
|
|
||||||
* ``select.devpoll()``
|
The default value of the *cloexec* parameter is
|
||||||
* ``select.poll()``
|
``sys.getdefaultcloexec()``.
|
||||||
* ``select.epoll()``
|
|
||||||
* ``select.kqueue()``
|
|
||||||
* ``socket.socket.recvmsg()``: use ``MSG_CMSG_CLOEXEC``,
|
|
||||||
or ``os.set_cloexec()``
|
|
||||||
|
|
||||||
The default value of the ``cloexec`` parameter is ``False`` to keep the
|
Add a new command line option ``-e`` and an environment variable
|
||||||
backward compatibility.
|
``PYTHONCLOEXEC`` to the set close-on-exec flag by default.
|
||||||
|
|
||||||
The close-on-exec flag will not be set on file descriptors 0 (stdin),
|
All functions creating file descriptors in the standard library must
|
||||||
1 (stdout) and 2 (stderr), because these files are expected to be
|
respect the default *cloexec* parameter (``sys.getdefaultcloexec()``).
|
||||||
inherited. It would still be possible to set close-on-exec flag
|
|
||||||
explicitly using ``os.set_cloexec()``.
|
|
||||||
|
|
||||||
Drawbacks:
|
File descriptors 0 (stdin), 1 (stdout) and 2 (stderr) are expected to be
|
||||||
|
inherited, but Python does not handle them differently. When
|
||||||
|
``os.dup2()`` is used to replace standard streams, ``cloexec=False``
|
||||||
|
must be specified explicitly.
|
||||||
|
|
||||||
* Many functions of the Python standard library creating file
|
Drawbacks of the proposal:
|
||||||
descriptors cannot be changed by this proposal, because adding
|
|
||||||
a ``cloexec`` optional parameter would be surprising and too many
|
* It is not more possible to know if the close-on-exec flag will be
|
||||||
functions would need it. For example, ``os.urandom()`` uses a
|
set or not on a newly created file descriptor just by reading the
|
||||||
temporary file on UNIX, but it calls a function of Windows API on
|
source code.
|
||||||
Windows. Adding a ``cloexec`` parameter to ``os.urandom()`` would
|
* If the inherance of a file descriptor matters, the *cloexec*
|
||||||
not make sense. See `Enable file descriptor inheritance by default`_
|
parameter must now be specified explicitly, or the library or the
|
||||||
for an incomplete list of functions creating file descriptors.
|
application will not work depending on the default value of the
|
||||||
* Checking if a module creates file descriptors is difficult. For
|
*cloexec* parameter.
|
||||||
example, ``os.urandom()`` creates a file descriptor on UNIX to read
|
|
||||||
``/dev/urandom`` (and closes it at exit), whereas it is implemented
|
|
||||||
using a function call on Windows. It is not possible to control
|
|
||||||
close-on-exec flag of the file descriptor used by ``os.urandom()``,
|
|
||||||
because ``os.urandom()`` API does not allow it.
|
|
||||||
|
|
||||||
|
|
||||||
Alternatives
|
Alternatives
|
||||||
============
|
============
|
||||||
|
|
||||||
Bikeshedding on the name of the new parameter
|
Enable inherance by default and no configurable default
|
||||||
---------------------------------------------
|
-------------------------------------------------------
|
||||||
|
|
||||||
* ``inherit``, ``inherited``: closer to Windows definition
|
Add a new optional parameter *cloexec* on functions creating file
|
||||||
* ``sensitive``
|
descriptors. The default value of the *cloexec* parameter is ``False``,
|
||||||
* ``sterile``: "Does not produce offspring."
|
and this default cannot be changed. No file descriptor inherance by
|
||||||
|
default is also the default on POSIX and on Windows. This alternative is
|
||||||
|
the most convervative option.
|
||||||
|
|
||||||
|
This option does solve issues listed in the `Rationale`_
|
||||||
|
section, it only provides an helper to fix them. All functions creating
|
||||||
|
file descriptors have to be modified to set *cloexec=True* in each
|
||||||
|
module used by an application to fix all these issues.
|
||||||
|
|
||||||
|
|
||||||
Enable file descriptor inheritance by default
|
Disable inheritance by default
|
||||||
---------------------------------------------
|
------------------------------
|
||||||
|
|
||||||
Set the close-on-exec flag by default on new file descriptors created
|
This alternative is based on the proposal: the only difference is that
|
||||||
by Python. This alternative just changes the default value of the new
|
the default value of the *cloexec* parameter is ``True`` (instead of
|
||||||
``cloexec`` parameter.
|
``False``).
|
||||||
|
|
||||||
If a file must be inherited by child processes, ``cloexec=False``
|
If a file must be inherited by child processes, ``cloexec=False``
|
||||||
parameter can be used.
|
parameter can be used.
|
||||||
|
@ -266,27 +274,6 @@ specify which file descriptors must be inherited. The close-on-exec
|
||||||
flag of these file descriptors must be changed with
|
flag of these file descriptors must be changed with
|
||||||
``os.set_cloexec()``.
|
``os.set_cloexec()``.
|
||||||
|
|
||||||
Example of functions creating file descriptors which will be modified
|
|
||||||
to set close-on-exec flag:
|
|
||||||
|
|
||||||
* ``os.urandom()`` (on UNIX)
|
|
||||||
* ``curses.window.getwin()``, ``curses.window.putwin()``
|
|
||||||
* ``mmap.mmap()`` (if ``MAP_ANONYMOUS`` is not defined)
|
|
||||||
* ``oss.open()``
|
|
||||||
* ``Modules/main.c``: ``RunStartupFile()``
|
|
||||||
* ``Python/pythonrun.c``: ``PyRun_SimpleFileExFlags()``
|
|
||||||
* ``Modules/getpath.c``: ``search_for_exec_prefix()``
|
|
||||||
* ``Modules/zipimport.c``: ``read_directory()``
|
|
||||||
* ``Modules/_ssl.c``: ``load_dh_params()``
|
|
||||||
* ``PC/getpathp.c``: ``calculate_path()``
|
|
||||||
* ``Python/errors.c``: ``PyErr_ProgramText()``
|
|
||||||
* ``Python/import.c``: ``imp_load_dynamic()``
|
|
||||||
* TODO: ``PC/_msi.c``
|
|
||||||
|
|
||||||
Many functions are impacted indirectly by this alternative. Examples:
|
|
||||||
|
|
||||||
* ``logging.FileHandler``
|
|
||||||
|
|
||||||
Advantages of setting close-on-exec flag by default:
|
Advantages of setting close-on-exec flag by default:
|
||||||
|
|
||||||
* There are far more programs that are bitten by FD inheritance upon
|
* There are far more programs that are bitten by FD inheritance upon
|
||||||
|
@ -296,6 +283,9 @@ Advantages of setting close-on-exec flag by default:
|
||||||
|
|
||||||
Drawbacks of setting close-on-exec flag by default:
|
Drawbacks of setting close-on-exec flag by default:
|
||||||
|
|
||||||
|
* It violates the principle of least surprise. Developers using the
|
||||||
|
os module may expect that Python respects the POSIX standard and so
|
||||||
|
that close-on-exec flag is not set by default.
|
||||||
* The os module is written as a thin wrapper to system calls (to
|
* The os module is written as a thin wrapper to system calls (to
|
||||||
functions of the C standard library). If atomic flags to set
|
functions of the C standard library). If atomic flags to set
|
||||||
close-on-exec flag are not supported (see `Appendix: Operating
|
close-on-exec flag are not supported (see `Appendix: Operating
|
||||||
|
@ -303,9 +293,6 @@ Drawbacks of setting close-on-exec flag by default:
|
||||||
system calls (see `Performances`_ section).
|
system calls (see `Performances`_ section).
|
||||||
* Extra system calls, if any, may slow down Python: see
|
* Extra system calls, if any, may slow down Python: see
|
||||||
`Performances`_.
|
`Performances`_.
|
||||||
* It violates the principle of least surprise. Developers using the
|
|
||||||
os module may expect that Python respects the POSIX standard and so
|
|
||||||
that close-on-exec flag is not set by default.
|
|
||||||
|
|
||||||
Backward compatibility: only a few programs rely on inherance of file
|
Backward compatibility: only a few programs rely on inherance of file
|
||||||
descriptors, and they only pass a few file descriptors, usually just
|
descriptors, and they only pass a few file descriptors, usually just
|
||||||
|
@ -319,48 +306,19 @@ parameter of Popen constructor. So it possible that these programs will
|
||||||
not need any fix if they use the ``subprocess`` module.
|
not need any fix if they use the ``subprocess`` module.
|
||||||
|
|
||||||
|
|
||||||
Add a function to set close-on-exec flag by default
|
|
||||||
---------------------------------------------------
|
|
||||||
|
|
||||||
An alternative is to add also a function to change globally the
|
|
||||||
default behaviour. It would be possible to set close-on-exec flag for
|
|
||||||
the whole application including all modules and the Python standard
|
|
||||||
library. This alternative is based on the `Proposal`_ and adds extra
|
|
||||||
changes.
|
|
||||||
|
|
||||||
New functions, command line argument and environment variable:
|
|
||||||
|
|
||||||
* ``sys.getdefaultcloexec() -> bool``: get the default value of the
|
|
||||||
*cloexec* parameter
|
|
||||||
* ``sys.setdefaultcloexec()``, ``-e`` command line option, ``PYTHONCLOEXEC``
|
|
||||||
environment variable (if set): set the default value of the *cloexec*
|
|
||||||
parameter to ``True``
|
|
||||||
|
|
||||||
The major change is that the default value of the ``cloexec`` parameter
|
|
||||||
is ``sys.getdefaultcloexec()``, instead of ``False``.
|
|
||||||
|
|
||||||
When ``sys.setdefaultcloexec()`` is called to set close-on-exec by default, we
|
|
||||||
have the same drawbacks as the `Enable file descriptor inheritance by default`_
|
|
||||||
alternative.
|
|
||||||
|
|
||||||
There are additionnal drawbacks of having two behaviours depending on
|
|
||||||
``sys.getdefaultcloexec()`` value:
|
|
||||||
|
|
||||||
* It is not more possible to know if the close-on-exec flag will be
|
|
||||||
set or not just by reading the source code.
|
|
||||||
|
|
||||||
|
|
||||||
Close file descriptors after fork
|
Close file descriptors after fork
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
This PEP does not fix issues with applications using ``fork()``
|
This PEP does not fix issues with applications using ``fork()``
|
||||||
without ``exec()``. Python needs a generic process to register
|
without ``exec()``. Python needs a generic process to register
|
||||||
callbacks which would be called after a fork, see `Add an 'atfork'
|
callbacks which would be called after a fork, see `#16500:
|
||||||
module`_. Such registry could be used to close file descriptors just
|
Add an atfork module`_. Such registry could be used to close file
|
||||||
after a ``fork()``.
|
descriptors just after a ``fork()``.
|
||||||
|
|
||||||
Drawbacks:
|
Drawbacks:
|
||||||
|
|
||||||
|
* It does not solve the problem on Windows: ``fork()`` does not exist
|
||||||
|
on Windows
|
||||||
* This alternative does not solve the problem for programs using
|
* This alternative does not solve the problem for programs using
|
||||||
``exec()`` without ``fork()``.
|
``exec()`` without ``fork()``.
|
||||||
* A third party module may call directly the C function ``fork()``
|
* A third party module may call directly the C function ``fork()``
|
||||||
|
@ -390,6 +348,16 @@ F_SETFD, FD_CLOEXEC)``. With Visual Studio, fopen() accepts a "N"
|
||||||
flag which uses ``O_NOINHERIT``.
|
flag which uses ``O_NOINHERIT``.
|
||||||
|
|
||||||
|
|
||||||
|
Bikeshedding on the name of the new parameter
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
* ``inherit``, ``inherited``: closer to Windows definition
|
||||||
|
* ``sensitive``
|
||||||
|
* ``sterile``: "Does not produce offspring."
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Applications using inherance of file descriptors
|
Applications using inherance of file descriptors
|
||||||
================================================
|
================================================
|
||||||
|
|
||||||
|
@ -402,19 +370,20 @@ No user complained about this behavior change yet.
|
||||||
Network servers using fork may want to pass the client socket to the
|
Network servers using fork may want to pass the client socket to the
|
||||||
child process. For example, on UNIX a CGI server pass the socket
|
child process. For example, on UNIX a CGI server pass the socket
|
||||||
client through file descriptors 0 (stdin) and 1 (stdout) using
|
client through file descriptors 0 (stdin) and 1 (stdout) using
|
||||||
``dup2()``. This specific case is not impacted by this PEP because the
|
``dup2()``.
|
||||||
close-on-exec flag is never set on file descriptors smaller than 3.
|
|
||||||
|
|
||||||
To access a restricted resource like creating a socket listening on a
|
To access a restricted resource like creating a socket listening on a
|
||||||
TCP port lower than 1024 or reading a file containing sensitive data
|
TCP port lower than 1024 or reading a file containing sensitive data
|
||||||
like passwords, a common practice is: start as the root user, create a
|
like passwords, a common practice is: start as the root user, create a
|
||||||
file descriptor, create a child process, pass the file descriptor to
|
file descriptor, create a child process, drop privileges (ex: change the
|
||||||
the child process and exit. Security is very important in such use
|
current user), pass the file descriptor to the child process and exit
|
||||||
case: leaking another file descriptor would be a critical security
|
the parent process.
|
||||||
vulnerability (see `Security`_). The root process may not exit but
|
|
||||||
monitors the child process instead, and restarts a new child process
|
Security is very important in such use case: leaking another file
|
||||||
and pass the same file descriptor if the previous child process
|
descriptor would be a critical security vulnerability (see `Security`_).
|
||||||
crashed.
|
The root process may not exit but monitors the child process instead,
|
||||||
|
and restarts a new child process and pass the same file descriptor if
|
||||||
|
the previous child process crashed.
|
||||||
|
|
||||||
Example of programs taking file descriptors from the parent process
|
Example of programs taking file descriptors from the parent process
|
||||||
using a command line option:
|
using a command line option:
|
||||||
|
@ -436,13 +405,13 @@ Setting close-on-exec flag may require additional system calls for
|
||||||
each creation of new file descriptors. The number of additional system
|
each creation of new file descriptors. The number of additional system
|
||||||
calls depends on the method used to set the flag:
|
calls depends on the method used to set the flag:
|
||||||
|
|
||||||
* ``O_NOINHERIT``: no additionnal system call
|
* ``O_NOINHERIT``: no additional system call
|
||||||
* ``O_CLOEXEC``: one addition system call, but only at the creation
|
* ``O_CLOEXEC``: one additional system call, but only at the creation
|
||||||
of the first file descriptor, to check if the flag is supported. If
|
of the first file descriptor, to check if the flag is supported. If
|
||||||
no, Python has to fallback to the next method.
|
the flag is not supported, Python has to fallback to the next method.
|
||||||
* ``ioctl(fd, FIOCLEX)``: one addition system call per file
|
* ``ioctl(fd, FIOCLEX)``: one additional system call per file
|
||||||
descriptor
|
descriptor
|
||||||
* ``fcntl(fd, F_SETFD, flags)``: two addition system calls per file
|
* ``fcntl(fd, F_SETFD, flags)``: two additional system calls per file
|
||||||
descriptor, one to get old flags and one to set new flags
|
descriptor, one to get old flags and one to set new flags
|
||||||
|
|
||||||
On Linux, setting the close-on-flag has a low overhead on performances.
|
On Linux, setting the close-on-flag has a low overhead on performances.
|
||||||
|
@ -560,8 +529,9 @@ os.dup2()
|
||||||
os.pipe()
|
os.pipe()
|
||||||
---------
|
---------
|
||||||
|
|
||||||
* Windows: ``CreatePipe()`` with ``SECURITY_ATTRIBUTES.bInheritHandle=TRUE``,
|
* Windows: ``CreatePipe()`` with
|
||||||
or ``_pipe()`` with ``O_NOINHERIT`` flag [atomic]
|
``SECURITY_ATTRIBUTES.bInheritHandle=TRUE``, or ``_pipe()`` with
|
||||||
|
``O_NOINHERIT`` flag [atomic]
|
||||||
* ``pipe2()`` with ``O_CLOEXEC`` flag [atomic]
|
* ``pipe2()`` with ``O_CLOEXEC`` flag [atomic]
|
||||||
* ``pipe()`` + ``os.set_cloexec(fd, True)`` [best-effort]
|
* ``pipe()`` + ``os.set_cloexec(fd, True)`` [best-effort]
|
||||||
|
|
||||||
|
@ -569,6 +539,7 @@ socket.socket()
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
* Windows: ``WSASocket()`` with ``WSA_FLAG_NO_HANDLE_INHERIT`` flag
|
* Windows: ``WSASocket()`` with ``WSA_FLAG_NO_HANDLE_INHERIT`` flag
|
||||||
|
[atomic]
|
||||||
* ``socket()`` with ``SOCK_CLOEXEC`` flag [atomic]
|
* ``socket()`` with ``SOCK_CLOEXEC`` flag [atomic]
|
||||||
* ``socket()`` + ``os.set_cloexec(fd, True)`` [best-effort]
|
* ``socket()`` + ``os.set_cloexec(fd, True)`` [best-effort]
|
||||||
|
|
||||||
|
@ -603,56 +574,63 @@ processes".
|
||||||
|
|
||||||
For example, it is supported by ``open()`` and ``_pipe()``.
|
For example, it is supported by ``open()`` and ``_pipe()``.
|
||||||
|
|
||||||
The value of the flag can be modified using:
|
The flag can be cleared using
|
||||||
``SetHandleInformation(fd, HANDLE_FLAG_INHERIT, 1)``.
|
``SetHandleInformation(fd, HANDLE_FLAG_INHERIT, 0)``.
|
||||||
|
|
||||||
``CreateProcess()`` has an ``bInheritHandles`` parameter: if it is
|
``CreateProcess()`` has an ``bInheritHandles`` parameter: if it is
|
||||||
FALSE, the handles are not inherited. It is used by
|
``FALSE``, the handles are not inherited. If it is ``TRUE``, handles
|
||||||
``subprocess.Popen`` with ``close_fds`` option.
|
with ``HANDLE_FLAG_INHERIT`` flag set are inherited.
|
||||||
|
``subprocess.Popen`` uses ``close_fds`` option to define
|
||||||
|
``bInheritHandles``.
|
||||||
|
|
||||||
fcntl
|
|
||||||
-----
|
|
||||||
|
|
||||||
Functions:
|
|
||||||
|
|
||||||
* ``fcntl(fd, F_GETFD)``
|
|
||||||
* ``fcntl(fd, F_SETFD, flags | FD_CLOEXEC)``
|
|
||||||
|
|
||||||
Availability: AIX, Digital UNIX, FreeBSD, HP-UX, IRIX, Linux, Mac OS
|
|
||||||
X, OpenBSD, Solaris, SunOS, Unicos.
|
|
||||||
|
|
||||||
ioctl
|
ioctl
|
||||||
-----
|
-----
|
||||||
|
|
||||||
Functions:
|
Functions:
|
||||||
|
|
||||||
* ``ioctl(fd, FIOCLEX, 0)`` sets close-on-exec flag
|
* ``ioctl(fd, FIOCLEX, 0)``: set the close-on-exec flag
|
||||||
* ``ioctl(fd, FIONCLEX, 0)`` clears close-on-exec flag
|
* ``ioctl(fd, FIONCLEX, 0)``: clear the close-on-exec flag
|
||||||
|
|
||||||
Availability: Linux, Mac OS X, QNX, NetBSD, OpenBSD, FreeBSD.
|
Availability: Linux, Mac OS X, QNX, NetBSD, OpenBSD, FreeBSD.
|
||||||
|
|
||||||
|
|
||||||
|
fcntl
|
||||||
|
-----
|
||||||
|
|
||||||
|
Functions:
|
||||||
|
|
||||||
|
* ``flags = fcntl(fd, F_GETFD); fcntl(fd, F_SETFD, flags | FD_CLOEXEC)``:
|
||||||
|
set the close-on-exec flag
|
||||||
|
* ``flags = fcntl(fd, F_GETFD); fcntl(fd, F_SETFD, flags & ~FD_CLOEXEC)``:
|
||||||
|
clear the close-on-exec flag
|
||||||
|
|
||||||
|
Availability: AIX, Digital UNIX, FreeBSD, HP-UX, IRIX, Linux, Mac OS
|
||||||
|
X, OpenBSD, Solaris, SunOS, Unicos.
|
||||||
|
|
||||||
|
|
||||||
Atomic flags
|
Atomic flags
|
||||||
------------
|
------------
|
||||||
|
|
||||||
New flags:
|
New flags:
|
||||||
|
|
||||||
* ``O_CLOEXEC``: available on Linux (2.6.23+), FreeBSD (8.3+),
|
* ``O_CLOEXEC``: available on Linux (2.6.23), FreeBSD (8.3),
|
||||||
OpenBSD 5.0, QNX, BeOS, next NetBSD release (6.1?). This flag is
|
OpenBSD 5.0, QNX, BeOS, next NetBSD release (6.1?). This flag is
|
||||||
part of POSIX.1-2008.
|
part of POSIX.1-2008.
|
||||||
* ``SOCK_CLOEXEC`` flag for ``socket()`` and ``socketpair()``,
|
* ``SOCK_CLOEXEC`` flag for ``socket()`` and ``socketpair()``,
|
||||||
available on Linux 2.6.27+, OpenBSD 5.2, NetBSD 6.0.
|
available on Linux 2.6.27, OpenBSD 5.2, NetBSD 6.0.
|
||||||
* ``WSA_FLAG_NO_HANDLE_INHERIT`` flag for ``WSASocket()``: supported on
|
* ``WSA_FLAG_NO_HANDLE_INHERIT`` flag for ``WSASocket()``: supported
|
||||||
Windows 7 with SP1, Windows Server 2008 R2 with SP1, and later
|
on Windows 7 with SP1, Windows Server 2008 R2 with SP1, and later
|
||||||
* ``fcntl()``: ``F_DUPFD_CLOEXEC`` flag, available on Linux 2.6.24+,
|
* ``fcntl()``: ``F_DUPFD_CLOEXEC`` flag, available on Linux 2.6.24,
|
||||||
OpenBSD 5.0, FreeBSD 9.1, NetBSD 6.0. This flag is part of
|
OpenBSD 5.0, FreeBSD 9.1, NetBSD 6.0. This flag is part of
|
||||||
POSIX.1-2008.
|
POSIX.1-2008.
|
||||||
* ``recvmsg()``: ``MSG_CMSG_CLOEXEC``, available on Linux 2.6.23+,
|
* ``recvmsg()``: ``MSG_CMSG_CLOEXEC``, available on Linux 2.6.23,
|
||||||
NetBSD 6.0.
|
NetBSD 6.0.
|
||||||
|
|
||||||
On Linux older than 2.6.23, ``O_CLOEXEC`` flag is simply ignored. So
|
On Linux older than 2.6.23, ``O_CLOEXEC`` flag is simply ignored. So
|
||||||
we have to check that the flag is supported by calling ``fcntl()``. If
|
we have to check that the flag is supported by calling ``fcntl()``. If
|
||||||
it does not work, we have to set the flag using ``fcntl()``.
|
it does not work, we have to set the flag using ``ioctl()`` or
|
||||||
|
``fcntl()``.
|
||||||
|
|
||||||
On Linux older than 2.6.27, if the ``SOCK_CLOEXEC`` flag is set in the
|
On Linux older than 2.6.27, if the ``SOCK_CLOEXEC`` flag is set in the
|
||||||
socket type, ``socket()`` or ``socketpair()`` fail and ``errno`` is set
|
socket type, ``socket()`` or ``socketpair()`` fail and ``errno`` is set
|
||||||
|
@ -660,9 +638,9 @@ to ``EINVAL``.
|
||||||
|
|
||||||
New functions:
|
New functions:
|
||||||
|
|
||||||
* ``dup3()``: available on Linux 2.6.27+ (and glibc 2.9)
|
* ``dup3()``: available on Linux 2.6.27 (and glibc 2.9)
|
||||||
* ``pipe2()``: available on Linux 2.6.27+ (and glibc 2.9)
|
* ``pipe2()``: available on Linux 2.6.27 (and glibc 2.9)
|
||||||
* ``accept4()``: available on Linux 2.6.28+ (and glibc 2.10)
|
* ``accept4()``: available on Linux 2.6.28 (and glibc 2.10)
|
||||||
|
|
||||||
If ``accept4()`` is called on Linux older than 2.6.28, ``accept4()``
|
If ``accept4()`` is called on Linux older than 2.6.28, ``accept4()``
|
||||||
returns ``-1`` (fail) and ``errno`` is set to ``ENOSYS``.
|
returns ``-1`` (fail) and ``errno`` is set to ``ENOSYS``.
|
||||||
|
@ -683,30 +661,34 @@ Links:
|
||||||
|
|
||||||
Python issues:
|
Python issues:
|
||||||
|
|
||||||
* `open() does not able to set flags, such as O_CLOEXEC
|
* `#10115: Support accept4() for atomic setting of flags at socket
|
||||||
|
creation <http://bugs.python.org/issue10115>`_
|
||||||
|
* `#12105: open() does not able to set flags, such as O_CLOEXEC
|
||||||
<http://bugs.python.org/issue12105>`_
|
<http://bugs.python.org/issue12105>`_
|
||||||
* `Add "e" mode to open(): close-and-exec (O_CLOEXEC) / O_NOINHERIT
|
* `#12107: TCP listening sockets created without FD_CLOEXEC flag
|
||||||
<http://bugs.python.org/issue16850>`_
|
|
||||||
* `TCP listening sockets created without FD_CLOEXEC flag
|
|
||||||
<http://bugs.python.org/issue12107>`_
|
<http://bugs.python.org/issue12107>`_
|
||||||
* `Use O_CLOEXEC in the tempfile module
|
* `#16500: Add an atfork module
|
||||||
<http://bugs.python.org/issue16860>`_
|
|
||||||
* `Support accept4() for atomic setting of flags at socket creation
|
|
||||||
<http://bugs.python.org/issue10115>`_
|
|
||||||
* `Add an 'atfork' module
|
|
||||||
<http://bugs.python.org/issue16500>`_
|
<http://bugs.python.org/issue16500>`_
|
||||||
* `Implementation of the PEP 433
|
* `#16850: Add "e" mode to open(): close-and-exec
|
||||||
|
(O_CLOEXEC) / O_NOINHERIT <http://bugs.python.org/issue16850>`_
|
||||||
|
* `#16860: Use O_CLOEXEC in the tempfile module
|
||||||
|
<http://bugs.python.org/issue16860>`_
|
||||||
|
* `#17036: Implementation of the PEP 433
|
||||||
<http://bugs.python.org/issue17036>`_
|
<http://bugs.python.org/issue17036>`_
|
||||||
|
* `#16946: subprocess: _close_open_fd_range_safe() does not set
|
||||||
|
close-on-exec flag on Linux < 2.6.23 if O_CLOEXEC is defined
|
||||||
|
<http://bugs.python.org/issue16946>`_
|
||||||
|
* `#17070: PEP 433: Use the new cloexec to improve security and avoid
|
||||||
|
bugs <http://bugs.python.org/issue17070>`_
|
||||||
|
|
||||||
Ruby:
|
Ruby:
|
||||||
|
|
||||||
* `Set FD_CLOEXEC for all fds (except 0, 1, 2)
|
* `Set FD_CLOEXEC for all fds (except 0, 1, 2)
|
||||||
<http://bugs.ruby-lang.org/issues/5041>`_
|
<http://bugs.ruby-lang.org/issues/5041>`_
|
||||||
* `O_CLOEXEC flag missing for Kernel::open
|
* `O_CLOEXEC flag missing for Kernel::open
|
||||||
<http://bugs.ruby-lang.org/issues/1291>`_:
|
<http://bugs.ruby-lang.org/issues/1291>`_: the
|
||||||
`commit reverted
|
`commit was reverted later
|
||||||
<http://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/31643>`_
|
<http://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/31643>`_
|
||||||
later
|
|
||||||
|
|
||||||
Footnotes
|
Footnotes
|
||||||
=========
|
=========
|
||||||
|
|
Loading…
Reference in New Issue