summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2013-06-07 20:50:59 +0200
committerRobin Gareus <robin@gareus.org>2013-06-07 20:50:59 +0200
commitb26cc125135feae4720d8910a8df3b0d2372f71b (patch)
treee8aad28e659b2ccdc57e9aa62af17ef3dcfbac9a
parentfd5f1ef5f531492ebe13011d8d875fee8eae090d (diff)
close all open fd's on fork
-rw-r--r--gtk2_ardour/system_exec.cc110
1 files changed, 110 insertions, 0 deletions
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 <robin@gareus.org>
This program is free software; you can redistribute it and/or modify
@@ -23,6 +24,9 @@
#include <errno.h>
#include <unistd.h>
+#include <assert.h>
+#include <dirent.h>
+
#ifdef __WIN32__
#include <windows.h>
#else
@@ -31,8 +35,11 @@
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/resource.h>
#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;