From b26cc125135feae4720d8910a8df3b0d2372f71b Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Fri, 7 Jun 2013 20:50:59 +0200 Subject: [PATCH] close all open fd's on fork --- gtk2_ardour/system_exec.cc | 110 +++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/gtk2_ardour/system_exec.cc b/gtk2_ardour/system_exec.cc index 90c7294f55..55dbc60bb4 100644 --- a/gtk2_ardour/system_exec.cc +++ b/gtk2_ardour/system_exec.cc @@ -1,5 +1,6 @@ /* Copyright (C) 2010 Paul Davis + Copyright 2005-2008 Lennart Poettering Author: Robin Gareus This program is free software; you can redistribute it and/or modify @@ -23,6 +24,9 @@ #include #include +#include +#include + #ifdef __WIN32__ #include #else @@ -31,8 +35,11 @@ #include #include #include +#include +#include #endif + #include "system_exec.h" using namespace std; @@ -40,6 +47,104 @@ void * interposer_thread (void *arg); static void close_fd (int& fd) { if (fd >= 0) ::close (fd); fd = -1; } +#ifndef __WIN32__ +/* + * This function was part of libasyncns. + * LGPL v2.1 + * Copyright 2005-2008 Lennart Poettering + */ +static int close_allv(const int except_fds[]) { + struct rlimit rl; + int fd; + +#ifdef __linux__ + + DIR *d; + + assert(except_fds); + + if ((d = opendir("/proc/self/fd"))) { + struct dirent *de; + + while ((de = readdir(d))) { + int found; + long l; + char *e = NULL; + int i; + + if (de->d_name[0] == '.') + continue; + + errno = 0; + l = strtol(de->d_name, &e, 10); + if (errno != 0 || !e || *e) { + closedir(d); + errno = EINVAL; + return -1; + } + + fd = (int) l; + + if ((long) fd != l) { + closedir(d); + errno = EINVAL; + return -1; + } + + if (fd < 3) + continue; + + if (fd == dirfd(d)) + continue; + + found = 0; + for (i = 0; except_fds[i] >= 0; i++) + if (except_fds[i] == fd) { + found = 1; + break; + } + + if (found) continue; + + if (close(fd) < 0) { + int saved_errno; + + saved_errno = errno; + closedir(d); + errno = saved_errno; + + return -1; + } + } + + closedir(d); + return 0; + } + +#endif + + if (getrlimit(RLIMIT_NOFILE, &rl) < 0) + return -1; + + for (fd = 0; fd < (int) rl.rlim_max; fd++) { + int i; + + if (fd <= 3) + continue; + + for (i = 0; except_fds[i] >= 0; i++) + if (except_fds[i] == fd) + continue; + + if (close(fd) < 0 && errno != EBADF) + return -1; + } + + return 0; +} +#endif /* not on windows */ + + SystemExec::SystemExec (std::string c, std::string a) : cmd(c) { @@ -619,6 +724,11 @@ SystemExec::start (int stderr_mode) signal(SIGPIPE, SIG_DFL); #endif +#ifndef __WIN32__ + int good_fds[1] = { 0 }; + close_allv(good_fds); +#endif + ::execve(argp[0], argp, envp); /* if we reach here something went wrong.. */ char buf = 0;