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
|
||||
========
|
||||
|
||||
This PEP proposes to add a new optional parameter ``cloexec`` on
|
||||
functions creating file descriptors in the Python standard library. If
|
||||
the parameter is ``True``, the close-on-exec flag will be set on the
|
||||
new file descriptor.
|
||||
Add a new optional *cloexec* parameter on functions creating file
|
||||
descriptors, add different ways to change default values of this
|
||||
parameter, and add four new functions:
|
||||
|
||||
* ``os.get_cloexec(fd)``
|
||||
* ``os.set_cloexec(fd, cloexec=True)``
|
||||
* ``sys.getdefaultcloexec()``
|
||||
* ``sys.setdefaultcloexec(cloexec=True)``
|
||||
|
||||
|
||||
Rationale
|
||||
|
@ -25,38 +29,42 @@ Rationale
|
|||
A file descriptor has a close-on-exec flag which indicates if the file
|
||||
descriptor will be inherited or not.
|
||||
|
||||
On UNIX, the file descriptor will be closed on the execution of child processes
|
||||
if the close-on-exec flag is set, the file descriptor is inherited by child
|
||||
processes if the flag is cleared.
|
||||
On UNIX, if the close-on-exec flag is set, the file descriptor is not
|
||||
inherited: it will be closed at the execution of child processes;
|
||||
otherwise the file descriptor is inherited by child processes.
|
||||
|
||||
On Windows, the file descriptor is not inherited if the close-on-exec flag is
|
||||
set, the file descriptor is inherited by child processes if the flag is cleared
|
||||
and if ``CreateProcess()`` is called with the *bInheritHandles* parameter set
|
||||
to ``TRUE`` (when ``subprocess.Popen`` is created with ``close_fds=False`` for
|
||||
example).
|
||||
On Windows, if the close-on-exec flag is set, the file descriptor is not
|
||||
inherited; the file descriptor is inherited by child processes if the
|
||||
close-on-exec flag is cleared and if ``CreateProcess()`` is called with
|
||||
the *bInheritHandles* parameter set to ``TRUE`` (when
|
||||
``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
|
||||
--------------------
|
||||
|
||||
On UNIX, the subprocess module closes file descriptors greater than 2 by
|
||||
default since Python 3.2 [#subprocess_close]_. All file descriptors created by
|
||||
the parent process are automatically closed in the child process.
|
||||
default since Python 3.2 [#subprocess_close]_. All file descriptors
|
||||
created by the parent process are automatically closed in the child
|
||||
process.
|
||||
|
||||
``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.
|
||||
|
||||
There are other cases creating a subprocess or executing a new program
|
||||
where file descriptors are not closed: functions of the os.spawn*()
|
||||
family and third party modules calling ``exec()`` or ``fork()`` +
|
||||
``exec()``. In this case, file descriptors are shared between the
|
||||
parent and the child processes which is usually unexpected and causes
|
||||
various issues.
|
||||
where file descriptors are not closed: functions of the ``os.spawn*()``
|
||||
and the ``os.exec*()`` families and third party modules calling
|
||||
``exec()`` or ``fork()`` + ``exec()``. In this case, file descriptors
|
||||
are shared between the parent and the child processes which is usually
|
||||
unexpected and causes various issues.
|
||||
|
||||
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.
|
||||
subprocess in Python 3.2, to fix the issue in any code, and not just
|
||||
code using subprocess.
|
||||
|
||||
|
||||
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
|
||||
child process.
|
||||
|
||||
The listening socket of TCPServer is not closed on ``exec()``: the
|
||||
child process is able to get connection from new clients; if the
|
||||
parent closes the listening socket and create a new listening socket
|
||||
on the same address, it would get an "address already is used" error.
|
||||
The listening socket of TCPServer is not closed on ``exec()``: the child
|
||||
process is able to get connection from new clients; if the parent closes
|
||||
the listening socket and create a new listening socket on the same
|
||||
address, it would get an "address already is used" error.
|
||||
|
||||
Not closing file descriptors can lead to resource exhaustion: even if
|
||||
the parent closes all files, creating a new file descriptor may fail
|
||||
with "too many files" because files are still open in the child
|
||||
process.
|
||||
with "too many files" because files are still open in the child process.
|
||||
|
||||
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
|
||||
``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 descriptors of the constructor the ``pass_fds`` parameter?
|
||||
|
||||
|
@ -185,78 +178,93 @@ XXX descriptors of the constructor the ``pass_fds`` parameter?
|
|||
Proposal
|
||||
========
|
||||
|
||||
This PEP proposes to add a new optional parameter ``cloexec`` on
|
||||
functions creating file descriptors in the Python standard library. If
|
||||
the parameter is ``True``, the close-on-exec flag will be set on the
|
||||
new file descriptor.
|
||||
Add a new optional *cloexec* parameter on functions creating file
|
||||
descriptors and different ways to change default values of this
|
||||
parameter.
|
||||
|
||||
Add a new functions:
|
||||
Add new functions:
|
||||
|
||||
* ``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
|
||||
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
|
||||
* ``os.dup()``, ``os.dup2()``
|
||||
* ``asyncore.dispatcher.create_socket()``
|
||||
* ``io.FileIO``
|
||||
* ``io.open()``
|
||||
* ``open()``
|
||||
* ``os.dup()``
|
||||
* ``os.dup2()``
|
||||
* ``os.fdopen()``
|
||||
* ``os.open()``
|
||||
* ``os.openpty()``
|
||||
* ``os.pipe()``
|
||||
* ``socket.socket()``, ``socket.socketpair()``,
|
||||
``socket.socket.accept()``
|
||||
* Maybe also: ``os.open()``, ``os.openpty()``
|
||||
* TODO:
|
||||
* ``select.devpoll()``
|
||||
* ``select.epoll()``
|
||||
* ``select.kqueue()``
|
||||
* ``socket.socket()``
|
||||
* ``socket.socket.accept()``
|
||||
* ``socket.socket.dup()``
|
||||
* ``socket.socket.fromfd``
|
||||
* ``socket.socketpair()``
|
||||
|
||||
* ``select.devpoll()``
|
||||
* ``select.poll()``
|
||||
* ``select.epoll()``
|
||||
* ``select.kqueue()``
|
||||
* ``socket.socket.recvmsg()``: use ``MSG_CMSG_CLOEXEC``,
|
||||
or ``os.set_cloexec()``
|
||||
The default value of the *cloexec* parameter is
|
||||
``sys.getdefaultcloexec()``.
|
||||
|
||||
The default value of the ``cloexec`` parameter is ``False`` to keep the
|
||||
backward compatibility.
|
||||
Add a new command line option ``-e`` and an environment variable
|
||||
``PYTHONCLOEXEC`` to the set close-on-exec flag by default.
|
||||
|
||||
The close-on-exec flag will not be set on file descriptors 0 (stdin),
|
||||
1 (stdout) and 2 (stderr), because these files are expected to be
|
||||
inherited. It would still be possible to set close-on-exec flag
|
||||
explicitly using ``os.set_cloexec()``.
|
||||
All functions creating file descriptors in the standard library must
|
||||
respect the default *cloexec* parameter (``sys.getdefaultcloexec()``).
|
||||
|
||||
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
|
||||
descriptors cannot be changed by this proposal, because adding
|
||||
a ``cloexec`` optional parameter would be surprising and too many
|
||||
functions would need it. For example, ``os.urandom()`` uses a
|
||||
temporary file on UNIX, but it calls a function of Windows API on
|
||||
Windows. Adding a ``cloexec`` parameter to ``os.urandom()`` would
|
||||
not make sense. See `Enable file descriptor inheritance by default`_
|
||||
for an incomplete list of functions creating file descriptors.
|
||||
* Checking if a module creates file descriptors is difficult. For
|
||||
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.
|
||||
Drawbacks of the proposal:
|
||||
|
||||
* It is not more possible to know if the close-on-exec flag will be
|
||||
set or not on a newly created file descriptor just by reading the
|
||||
source code.
|
||||
* If the inherance of a file descriptor matters, the *cloexec*
|
||||
parameter must now be specified explicitly, or the library or the
|
||||
application will not work depending on the default value of the
|
||||
*cloexec* parameter.
|
||||
|
||||
|
||||
Alternatives
|
||||
============
|
||||
|
||||
Bikeshedding on the name of the new parameter
|
||||
---------------------------------------------
|
||||
Enable inherance by default and no configurable default
|
||||
-------------------------------------------------------
|
||||
|
||||
* ``inherit``, ``inherited``: closer to Windows definition
|
||||
* ``sensitive``
|
||||
* ``sterile``: "Does not produce offspring."
|
||||
Add a new optional parameter *cloexec* on functions creating file
|
||||
descriptors. The default value of the *cloexec* parameter is ``False``,
|
||||
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
|
||||
by Python. This alternative just changes the default value of the new
|
||||
``cloexec`` parameter.
|
||||
This alternative is based on the proposal: the only difference is that
|
||||
the default value of the *cloexec* parameter is ``True`` (instead of
|
||||
``False``).
|
||||
|
||||
If a file must be inherited by child processes, ``cloexec=False``
|
||||
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
|
||||
``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:
|
||||
|
||||
* 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:
|
||||
|
||||
* 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
|
||||
functions of the C standard library). If atomic flags to set
|
||||
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).
|
||||
* Extra system calls, if any, may slow down Python: see
|
||||
`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
|
||||
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.
|
||||
|
||||
|
||||
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
|
||||
---------------------------------
|
||||
|
||||
This PEP does not fix issues with applications using ``fork()``
|
||||
without ``exec()``. Python needs a generic process to register
|
||||
callbacks which would be called after a fork, see `Add an 'atfork'
|
||||
module`_. Such registry could be used to close file descriptors just
|
||||
after a ``fork()``.
|
||||
callbacks which would be called after a fork, see `#16500:
|
||||
Add an atfork module`_. Such registry could be used to close file
|
||||
descriptors just after a ``fork()``.
|
||||
|
||||
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
|
||||
``exec()`` without ``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``.
|
||||
|
||||
|
||||
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
|
||||
================================================
|
||||
|
||||
|
@ -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
|
||||
child process. For example, on UNIX a CGI server pass the socket
|
||||
client through file descriptors 0 (stdin) and 1 (stdout) using
|
||||
``dup2()``. This specific case is not impacted by this PEP because the
|
||||
close-on-exec flag is never set on file descriptors smaller than 3.
|
||||
``dup2()``.
|
||||
|
||||
To access a restricted resource like creating a socket listening on a
|
||||
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
|
||||
file descriptor, create a child process, pass the file descriptor to
|
||||
the child process and exit. Security is very important in such use
|
||||
case: leaking another file descriptor would be a critical security
|
||||
vulnerability (see `Security`_). 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.
|
||||
file descriptor, create a child process, drop privileges (ex: change the
|
||||
current user), pass the file descriptor to the child process and exit
|
||||
the parent process.
|
||||
|
||||
Security is very important in such use case: leaking another file
|
||||
descriptor would be a critical security vulnerability (see `Security`_).
|
||||
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
|
||||
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
|
||||
calls depends on the method used to set the flag:
|
||||
|
||||
* ``O_NOINHERIT``: no additionnal system call
|
||||
* ``O_CLOEXEC``: one addition system call, but only at the creation
|
||||
* ``O_NOINHERIT``: no additional system call
|
||||
* ``O_CLOEXEC``: one additional system call, but only at the creation
|
||||
of the first file descriptor, to check if the flag is supported. If
|
||||
no, Python has to fallback to the next method.
|
||||
* ``ioctl(fd, FIOCLEX)``: one addition system call per file
|
||||
the flag is not supported, Python has to fallback to the next method.
|
||||
* ``ioctl(fd, FIOCLEX)``: one additional system call per file
|
||||
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
|
||||
|
||||
On Linux, setting the close-on-flag has a low overhead on performances.
|
||||
|
@ -560,8 +529,9 @@ os.dup2()
|
|||
os.pipe()
|
||||
---------
|
||||
|
||||
* Windows: ``CreatePipe()`` with ``SECURITY_ATTRIBUTES.bInheritHandle=TRUE``,
|
||||
or ``_pipe()`` with ``O_NOINHERIT`` flag [atomic]
|
||||
* Windows: ``CreatePipe()`` with
|
||||
``SECURITY_ATTRIBUTES.bInheritHandle=TRUE``, or ``_pipe()`` with
|
||||
``O_NOINHERIT`` flag [atomic]
|
||||
* ``pipe2()`` with ``O_CLOEXEC`` flag [atomic]
|
||||
* ``pipe()`` + ``os.set_cloexec(fd, True)`` [best-effort]
|
||||
|
||||
|
@ -569,6 +539,7 @@ socket.socket()
|
|||
---------------
|
||||
|
||||
* Windows: ``WSASocket()`` with ``WSA_FLAG_NO_HANDLE_INHERIT`` flag
|
||||
[atomic]
|
||||
* ``socket()`` with ``SOCK_CLOEXEC`` flag [atomic]
|
||||
* ``socket()`` + ``os.set_cloexec(fd, True)`` [best-effort]
|
||||
|
||||
|
@ -603,56 +574,63 @@ processes".
|
|||
|
||||
For example, it is supported by ``open()`` and ``_pipe()``.
|
||||
|
||||
The value of the flag can be modified using:
|
||||
``SetHandleInformation(fd, HANDLE_FLAG_INHERIT, 1)``.
|
||||
The flag can be cleared using
|
||||
``SetHandleInformation(fd, HANDLE_FLAG_INHERIT, 0)``.
|
||||
|
||||
``CreateProcess()`` has an ``bInheritHandles`` parameter: if it is
|
||||
FALSE, the handles are not inherited. It is used by
|
||||
``subprocess.Popen`` with ``close_fds`` option.
|
||||
``FALSE``, the handles are not inherited. If it is ``TRUE``, handles
|
||||
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
|
||||
-----
|
||||
|
||||
Functions:
|
||||
|
||||
* ``ioctl(fd, FIOCLEX, 0)`` sets close-on-exec flag
|
||||
* ``ioctl(fd, FIONCLEX, 0)`` clears close-on-exec flag
|
||||
* ``ioctl(fd, FIOCLEX, 0)``: set the close-on-exec flag
|
||||
* ``ioctl(fd, FIONCLEX, 0)``: clear the close-on-exec flag
|
||||
|
||||
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
|
||||
------------
|
||||
|
||||
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
|
||||
part of POSIX.1-2008.
|
||||
* ``SOCK_CLOEXEC`` flag for ``socket()`` and ``socketpair()``,
|
||||
available on Linux 2.6.27+, OpenBSD 5.2, NetBSD 6.0.
|
||||
* ``WSA_FLAG_NO_HANDLE_INHERIT`` flag for ``WSASocket()``: supported on
|
||||
Windows 7 with SP1, Windows Server 2008 R2 with SP1, and later
|
||||
* ``fcntl()``: ``F_DUPFD_CLOEXEC`` flag, available on Linux 2.6.24+,
|
||||
available on Linux 2.6.27, OpenBSD 5.2, NetBSD 6.0.
|
||||
* ``WSA_FLAG_NO_HANDLE_INHERIT`` flag for ``WSASocket()``: supported
|
||||
on Windows 7 with SP1, Windows Server 2008 R2 with SP1, and later
|
||||
* ``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
|
||||
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.
|
||||
|
||||
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
|
||||
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
|
||||
socket type, ``socket()`` or ``socketpair()`` fail and ``errno`` is set
|
||||
|
@ -660,9 +638,9 @@ to ``EINVAL``.
|
|||
|
||||
New functions:
|
||||
|
||||
* ``dup3()``: 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)
|
||||
* ``dup3()``: 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)
|
||||
|
||||
If ``accept4()`` is called on Linux older than 2.6.28, ``accept4()``
|
||||
returns ``-1`` (fail) and ``errno`` is set to ``ENOSYS``.
|
||||
|
@ -683,30 +661,34 @@ Links:
|
|||
|
||||
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>`_
|
||||
* `Add "e" mode to open(): close-and-exec (O_CLOEXEC) / O_NOINHERIT
|
||||
<http://bugs.python.org/issue16850>`_
|
||||
* `TCP listening sockets created without FD_CLOEXEC flag
|
||||
* `#12107: TCP listening sockets created without FD_CLOEXEC flag
|
||||
<http://bugs.python.org/issue12107>`_
|
||||
* `Use O_CLOEXEC in the tempfile 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
|
||||
* `#16500: Add an atfork module
|
||||
<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>`_
|
||||
* `#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:
|
||||
|
||||
* `Set FD_CLOEXEC for all fds (except 0, 1, 2)
|
||||
<http://bugs.ruby-lang.org/issues/5041>`_
|
||||
* `O_CLOEXEC flag missing for Kernel::open
|
||||
<http://bugs.ruby-lang.org/issues/1291>`_:
|
||||
`commit reverted
|
||||
<http://bugs.ruby-lang.org/issues/1291>`_: the
|
||||
`commit was reverted later
|
||||
<http://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/31643>`_
|
||||
later
|
||||
|
||||
Footnotes
|
||||
=========
|
||||
|
|
Loading…
Reference in New Issue