Close all file descriptors when calling posix_spawn

I would like to create a set of processes using posix_spawn (...) (or something very similar). This function takes an argument of type posix_spawn_file_actions_t, which allows me to specify how to handle open file descriptors. From what I can confirm from the documentation , all files are inherited from the calling processes and changed according to the information in the posix_spawn_file_actions_t structure.

I want all files to be undisclosed using the spawned process (except stdin, stdout and stderr). Does anyone know how to do this? Apparently, this can be done in some implementations using the attribute attribute "POSIX_SPAWN_CLOEXEC_DEFAULT", but this is not available on my platform. I could also use fcntl (...) to indicate "close to exec" whenever I open the file, but I feel that a more localized solution for this problem would be preferable.

+3
source share
2 answers

Open the file descriptor handler through fork()and exec*()in a multi-threaded application, using file leases and / or fcntl()locks (write locks) are risky.

O_CLOEXEC/fcntl(fd, F_SETFD, FD_CLOEXEC) , . , , .

, Linux fcntl() fork(); . man 2 fork.

posix_spawn() C, posix_spawn_file_actions_init(), posix_spawn_file_actions_addclose() ; . . , exec*() .

- O_CLOEXEC / fcntl(fd,F_SETFD,FD_CLOEXEC), . -

#define _GNU_SOURCE
#define _POSIX_C_SOURCE 200809L
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/resource.h>

void set_all_close_on_exec(void)
{
    struct rlimit  rlim;
    long           max;
    int            fd;

    /* Resource limit? */
#if defined(RLIMIT_NOFILE)
    if (getrlimit(RLIMIT_NOFILE, &rlim) != 0)
        rlim.rlim_max = 0;
#elif defined(RLIMIT_OFILE)
    if (getrlimit(RLIMIT_OFILE, &rlim) != 0)
        rlim.rlim_max = 0;
#else
    /* POSIX: 8 message queues, 20 files, 8 streams */
    rlim.rlim_max = 36;
#endif

    /* Configured limit? */
#if defined(_SC_OPEN_MAX)
    max = sysconf(_SC_OPEN_MAX);
#else
    max = 36L;
#endif

    /* Use the bigger of the two. */
    if ((int)max > (int)rlim.rlim_max)
        fd = max;
    else
        fd = rlim.rlim_max;

    while (fd-->0)
        if (fd != STDIN_FILENO  &&
            fd != STDOUT_FILENO &&
            fd != STDERR_FILENO)
            fcntl(fd, F_SETFD, FD_CLOEXEC);
}

- ( ) close-on-exec; O_CLOEXEC. set_all_close_on_exec() 0.25ms ; 4096 1024 , 4093 .

( , fcntl(fd,F_SETFD,FD_CLOEXEC) errno==EBADF (/) .)

, , , . ( Linux , , /proc/self/fd/.)

-, , ( ) .

int do_exec(pid_t *const childptr,
            const char *const cmd,
            const char *const args[],
            const int stdin_fd,
            const int stdout_fd,
            const int stderr_fd);

My do_exec() close-on-exec, . ( exec(), errno char . char . , exec : , , , waitpid(), errno. , - exec(), ( ) ).

, , , , Unix ( , ), . , , , Apache mod_cgid FastCGI.

+7

FD_CLOEXEC ( fcntl()) open() O_CLOEXEC.

posix_spawn()::

file_actions - , , , , , FD_CLOEXEC (. fcntl()).

+2

All Articles