[Python-Dev] PEP 433: Add cloexec argument to functions creating file descriptors

Nick Coghlan ncoghlan at gmail.com
Sun Jan 13 12:13:42 CET 2013


On Sun, Jan 13, 2013 at 8:40 PM, Charles-François Natali
<cf.natali at gmail.com> wrote:
> Hello,
>
>> PEP: 433
>> Title: Add cloexec argument to functions creating file descriptors
>
> I'm not a native English speaker, but it seems to me that the correct
> wording should be "parameter" (part of the function
> definition/prototype, whereas "argument" refers to the actual value
> supplied).

This is correct (although it's a subtle distinction that even many
native English speakers get wrong).

For the PEP, I'd actually avoid assuming the solution in the title and
instead say something like "Easier suppression of file descriptor
inheritance"

>> This PEP proposes to add a new optional argument ``cloexec`` on
>> functions creating file descriptors in the Python standard library. If
>> the argument is ``True``, the close-on-exec flag will be set on the
>> new file descriptor.
>
> It would probably be useful to recap briefly what the close-on-exec flag does.
>
> Also, ISTM that Windows also supports this flag. If it does, then
> "cloexec" might not be the best name, because it refers to the
> execve() Unix system call. Maybe something like "noinherit" would be
> clearer (although coming from a Unix background "cloexec" is
> crystal-clear to me :-).

Indeed, this may be an area where following the underlying standards
too closely may not be a good idea. In particular, a *descriptive*
flag may be better choice than an imperative one.

For example, if we make the flag "sensitive", then the programmer is
telling us "this file descriptor is sensitive" and then we get to
decide what that means in terms of the underlying OS behaviours like
"close-on-exec" and "no-inherit" (as well as deciding whether or not
file descriptors are considered sensitive by default).

It also means we're free to implement a mechanism that tries to close
all sensitive file descriptors in _PyOS_AfterFork.

Alternatively, you could flip the sense of the flag and use
"inherited" - the scope is then clearly limited to indicating whether
or not the file descriptor should be inherited by child processes.

Either way, if done with sufficient advance warning and clear advice
to users, the "It's a systematic fix to adopt secure-by-default
behaviour" excuse may actually let it get by, especially if the
appropriate stdlib APIs adopt "inherited-by-default" for the FDs where
it is needed (such as subprocess pass_fds).


>> Add a new optional ``cloexec`` argument to:
>>
>>  * Maybe also: ``os.open()``, ``os.openpty()``
>
> Open can be passed O_CLOEXEC directly.

Indeed, people playing at the os module layer are already expected to
have to deal with platform specific behaviour. That's probably a
reasonable model to continue here - if people want cross-platform
handling of sensitive file descriptors, they either have to handle it
themselves or step up a layer of abstraction.

> Also, it has the same drawbacks as global variables: not thread-safe,
> not library-safe (i.e. if two libraries set it to conflicting values,
> you don't know which one is picked up).

I think it makes sense to consider the two issues separately, while
making sure the design in this PEP supports both "given inherited FD
by default, mark individual ones that shouldn't be inherited" and
"given non-inherited FD by default, mark individual ones for
inheritance"

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia


More information about the Python-Dev mailing list