Bug 57671

Summary: New function for apr_proc_detach() + close ALL file descriptors
Product: APR Reporter: Philipp Hahn <hahn>
Component: APRAssignee: Apache Portable Runtime bugs mailinglist <bugs>
Severity: enhancement CC: ylavic.dev
Priority: P2    
Version: HEAD   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Attachments: Demo-implementation of close_fds()

Description Philipp Hahn 2015-03-06 10:13:25 UTC
apr_proc_detach() (as called by apache-2.2.22) does only close STDIN, STDOUT, STDERR, but not all other (open) file descriptors.

This is problematic when apache2 is restarted from an unclean environment, where other file descriptors are opened and are pipes, as this happens for example with <https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=713967>: As the forked Apache process inherits the pipe, it is considered a potential writer, so any reading will block indefinitely instead of getting an EOF.

(Daemons not closing all file descriptors is a common problem, for which DebConf has an extra FQA entry: <http://www.fifi.org/doc/debconf-doc/tutorial.html#AEN198>)

As far as I know daemons should close all file descriptors:
- <http://linux.die.net/man/1/daemonize>
- <http://stackoverflow.com/questions/17954432/creating-a-daemon-in-linux>
- <http://en.wikipedia.org/wiki/Daemon_(computing)#Creating>

Closing all open file descriptors is somehow problematic, as there is no portable function for it. Because of that daemons normally implement a loop to close all FDs:

    int x;
    for (x = sysconf(_SC_OPEN_MAX); x>0; x--)
        close (x);

For Linux one can optimize that by using apr_dir_open(..., "/proc/self/fd", ...) to only close the open FDs.

IMHO apr_proc_detach() should implement the generic close-all-FDs semantic instead of only Apache-httpd doing it.
Comment 1 Philipp Hahn 2015-03-06 12:53:32 UTC
Created attachment 32548 [details]
Demo-implementation of close_fds()

gcc -Wall -o apache-closefd apache-closefd.c && ./apache-closefd 42>/dev/null
Comment 2 Yann Ylavic 2015-03-16 15:03:51 UTC
apr_proc_detach() does exactly what it is meant to: make the current process detach from the terminal (close STDIN/OUT/ERR) and, if daemonize is specified (not the daemonize tool!), make the current process have its own session (go background).

Should it close all open descriptors now that could/would break existing applications, those which currently open file descriptors before apr_proc_detach() and use them after (note that apr_proc_detach() already takes care of not closing the standard descriptors, but rather reopen them so that next opened descriptors won't "hijack" STDIN/OUT/ERR).

Maybe the APR could introduce a new function for this, but IMHO this already as simple as opening fds on a dedicated pool which could then be cleared before apr_proc_detach() is called. For fds that are not handled by the APR, it seems quite tricky to let the APR close them...
Comment 3 Jeff Trawick 2015-04-04 19:06:48 UTC
I also don't think apr has a role here to free arbitrary handles (other devs can of course disagree and re-open).

The best place to address this issue is in the caller of httpd, but maybe httpd could have a role, controlled by some -Dxxx command-line arg.  (Does httpd and its arbitrary plug-in modules have no fds it needs to preserve across the detach?  I don't understand how any code would know, but that's not a concern for this apr bug ;) )