summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2019-11-20 08:43:26 +0000
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2019-11-27 16:52:49 +0000
commit1127409564ed41ac1d0f9494b15abc9ba1280449 (patch)
tree30f831d593d8747b69521ea67fd7c089401d18ec
parentdd941fe4f80c93b65e2a1d11c7577a61b20ef047 (diff)
downloadefl-1127409564ed41ac1d0f9494b15abc9ba1280449.tar.gz
eina - add portable close all fd's we don't need function
close all fd's starting at a given fd and then leving out an exception list specially passed, if any. useful for fork+exec. this uses it in efl's fork+exec paths. @feat
-rw-r--r--src/lib/ecore/ecore_exe_posix.c4
-rw-r--r--src/lib/ecore/efl_exe.c5
-rw-r--r--src/lib/eina/eina_file.c84
-rw-r--r--src/lib/eina/eina_file.h17
4 files changed, 110 insertions, 0 deletions
diff --git a/src/lib/ecore/ecore_exe_posix.c b/src/lib/ecore/ecore_exe_posix.c
index 6a0cc3b79e..4a9b7a3338 100644
--- a/src/lib/ecore/ecore_exe_posix.c
+++ b/src/lib/ecore/ecore_exe_posix.c
@@ -364,6 +364,10 @@ _impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe)
E_NO_ERRNO(result, close(statusPipe[0]), ok);
E_IF_NO_ERRNO(result, eina_file_close_on_exec(statusPipe[1], EINA_TRUE), ok) /* close on exec shows success */
{
+ int except[2] = { 0, -1 };
+
+ except[0] = statusPipe[1];
+ eina_file_close_from(3, except);
/* Run the actual command. */
_ecore_exe_exec_it(exe_cmd, flags); /* no return */
}
diff --git a/src/lib/ecore/efl_exe.c b/src/lib/ecore/efl_exe.c
index f6ae3bfdde..8609dbfac5 100644
--- a/src/lib/ecore/efl_exe.c
+++ b/src/lib/ecore/efl_exe.c
@@ -540,6 +540,11 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
pd->env = NULL;
}
+ // close all fd's other than the first 3 (0, 1, 2) and exited write fd
+ int except[2] = { 0, -1 };
+ except[0] = pd->fd.exited_write;
+ eina_file_close_from(3, except);
+
// actually execute!
_exec(cmd, pd->flags, td->flags);
// we couldn't exec... uh oh. HAAAAAAAALP!
diff --git a/src/lib/eina/eina_file.c b/src/lib/eina/eina_file.c
index f4d0e7221c..6277ad6a3e 100644
--- a/src/lib/eina/eina_file.c
+++ b/src/lib/eina/eina_file.c
@@ -36,6 +36,10 @@
#endif
#include <fcntl.h>
+#ifdef HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
+#endif
+
#define PATH_DELIM '/'
#include "eina_config.h"
@@ -1252,3 +1256,83 @@ eina_file_statat(void *container, Eina_File_Direct_Info *info, Eina_Stat *st)
return 0;
}
+EAPI void
+eina_file_close_from(int fd, int *except_fd)
+{
+#if defined(_WIN32)
+ // XXX: what do to here? anything?
+#else
+#ifdef HAVE_DIRENT_H
+ DIR *dir;
+
+ dir = opendir("/proc/sefl/fd");
+ if (!dir) dir = opendir("/dev/fd");
+ if (dir)
+ {
+ struct dirent *dp;
+ const char *fname;
+ int *closes = NULL;
+ int num_closes = 0, i;
+
+ for (;;)
+ {
+skip:
+ dp = readdir(dir);
+ if (!dp) break;
+ fname = dp->d_name;
+
+ if ((fname[0] >= '0') && (fname[0] <= '9'))
+ {
+ int num = atoi(fname);
+ if (num >= fd)
+ {
+ if (except_fd)
+ {
+ int j;
+
+ for (j = 0; except_fd[j] >= 0; j++)
+ {
+ if (except_fd[j] == num) goto skip;
+ }
+ }
+ num_closes++;
+ int *tmp = realloc(closes, num_closes * sizeof(int));
+ if (!tmp) num_closes--;
+ else
+ {
+ closes = tmp;
+ closes[num_closes - 1] = num;
+ }
+ }
+ }
+ }
+ closedir(dir);
+ for (i = 0; i < num_closes; i++) close(closes[i]);
+ free(closes);
+ return;
+ }
+#endif
+ int i, max = 1024;
+
+# ifdef HAVE_SYS_RESOURCE_H
+ struct rlimit lim;
+ if (getrlimit(RLIMIT_NOFILE, &lim) < 0) return;
+ max = lim.rlim_max;
+# endif
+ for (i = fd; i < max;)
+ {
+ if (except_fd)
+ {
+ int j;
+
+ for (j = 0; except_fd[j] >= 0; j++)
+ {
+ if (except_fd[j] == i) goto skip2;
+ }
+ }
+ close(i);
+skip2:
+ i++;
+ }
+#endif
+}
diff --git a/src/lib/eina/eina_file.h b/src/lib/eina/eina_file.h
index ade3b4fd79..404dea1ccb 100644
--- a/src/lib/eina/eina_file.h
+++ b/src/lib/eina/eina_file.h
@@ -348,6 +348,23 @@ EAPI Eina_Iterator *eina_file_stat_ls(const char *dir) EINA_WARN_UNUSED_RESULT E
EAPI int eina_file_statat(void *container, Eina_File_Direct_Info *info, Eina_Stat *buf) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1, 2, 3);
/**
+ * @brief Close all file descriptors that are open at or above the given fd
+ * @details This closes all open file descriptors that are equal to or of
+ * higher value than the given inpit fd given. This is intended for
+ * niche use like closing all open files just before exec()ing a
+ * new process after calling fork(). The except_fd array can be NULL
+ * if no fd's are to be skipped, but if some fd's are to skip being
+ * closed then this will be an array of fd numbers being terminated
+ * by a fd value of -1.
+ *
+ * @param[in] fd The fd value to begin closing at
+ * @param[in] except_fd An array of fd's not to close terminated by -1 as the last invalid fd
+ *
+ * @since 1.24
+ */
+EAPI void eina_file_close_from(int fd, int *except_fd);
+
+/**
* @brief Generates and creates a uniquely named temporary file from a template name.
* The generated file is opened with the open(2) @c O_EXCL flag.
* @details This function calls mkstemp(), generates a unique temporary filename