Bug 10353 - Methods for deleting all file descriptors greater than given integer
Summary: Methods for deleting all file descriptors greater than given integer
Status: RESOLVED WONTFIX
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Ulrich Drepper
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-06-30 23:31 IST by Martin Buchholz
Modified: 2014-07-01 07:53 IST (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Buchholz 2009-06-30 23:31:09 IST
Recent Solaris provides a way to delete all file descriptors
greater than a given integer, and provides a way to ask
posix_spawn to do so.  I believe glibc should implement these extensions.

Both of the big programs I have worked on, xemacs and openjdk,
have written their own way to do this.

extern int posix_spawn_file_actions_addclosefrom_np(
	posix_spawn_file_actions_t *file_actions,
	int lowfiledes);

extern void closefrom(int);

http://docs.sun.com/app/docs/doc/819-2243/posix-spawn-file-actions-addclosefrom-np-3c?l=ja&a=view

http://docs.sun.com/app/docs/doc/819-2243/closefrom-3c?l=ja&a=view

The functionality that has been added to glibc allowing FD_CLOSE_ON_EXEC
to be specified at time of creation of the fd does help (thank you)
but it is not sufficient for "open" programs like the JDK where 
arbitrary third party native code may be concurrently opening file 
descriptors while creating a subprocess.
Comment 1 Roland McGrath 2009-06-30 23:52:42 IST
nscd.c does this by hand in a Linux-specific way, and it is trivial to implement
in libc on Hurd.  So this seems like a good addition.
Comment 2 Ulrich Drepper 2009-07-01 05:57:37 IST
No, it's a horrible idea.  The assumption that a program knows all the open file
descriptors is simply invalid.  The runtime (all kinds of libraries) can at any
point in time create additional file descriptors and indiscriminately calls for
trouble.  The correct way is to name the individual file descriptors the program
knows about and let the creator of the other file descriptors worry about the rest.

The reason nscd can do it the way it does it is simple: all the code used is
controlled by libc.  But that's a special case.
Comment 3 Martin Buchholz 2009-07-01 22:22:36 IST
Aside from the Solaris 10 precedent, other OSes have adopted
closefrom, apparently with the same behavior.

Here's OpenBSD:

http://www.openbsd.org/cgi-bin/man.cgi?query=closefrom&apropos=0&sektion=0&manpath=OpenBSD+Current&arch=i386&format=html

Here's NetBSD:

http://netbsd.gw.com/cgi-bin/man-cgi?closefrom++NetBSD-current

To provide more motivation, the idea is that you are in a
large multithreaded app that is swimming in a sea of unknown
file descriptors that may or may not have FD_CLOEXEC set,
you fork(), frob some file descriptors you care about,
and then need to close the rest.  You write your own buggy closefrom
or use the one provided by the system.
Comment 4 Ulrich Drepper 2009-07-02 06:27:45 IST
(In reply to comment #3)
> Here's OpenBSD:
> [...]
> Here's NetBSD:
> [...]

This is *anything* but an argument in favor.


> To provide more motivation, the idea is that you are in a
> large multithreaded app that is swimming in a sea of unknown
> file descriptors that may or may not have FD_CLOEXEC set,

So, fix the code.  We have O_CLOEXEC support as well.  There is no reason to
work around buggy code and this interface *actively* prevents innovations by
usurping file descriptors.
Comment 5 Martin Buchholz 2009-07-02 16:14:46 IST
>> To provide more motivation, the idea is that you are in a
>> large multithreaded app that is swimming in a sea of unknown
>> file descriptors that may or may not have FD_CLOEXEC set,

>So, fix the code.  We have O_CLOEXEC support as well.  There is no reason to
>work around buggy code and this interface *actively* prevents innovations by
>usurping file descriptors.

For many applications, there is no way in practice to control all the 
code running in the same address space.  This is especially true for
"platforms" like java, where arbitrary user-created shared libraries
are loaded and executed at runtime.

The idea of permitting innovations that use file descriptors is
an interesting one, but one that in my opinion cannot succeed.
Too many people (like myself) are maintaining library code
that starts new subprocesses, and they will continue to
indiscriminately close unknown file descriptors, 
with or without help from their libc.

While my library closes file descriptors unconditionally,
The python subprocess API makes closing fds an option.

"""If close_fds is true, all file descriptors except 0, 1 and 2 will be
closed before the child process is executed."""

Interestingly, python provides a related function

.. function:: closerange(fd_low, fd_high)

   Close all file descriptors from *fd_low* (inclusive) to *fd_high* (exclusive),
   ignoring errors. Availability: Unix, Windows. Equivalent to::

      for fd in xrange(fd_low, fd_high):
          try:
              os.close(fd)
          except OSError:
              pass

which doesn't seem to support "infinity" for the second argument.