[vte] lib: Move fdwalk fallback implementation to its own file
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vte] lib: Move fdwalk fallback implementation to its own file
- Date: Mon, 27 Apr 2020 18:50:56 +0000 (UTC)
commit 69ed779091b4165b8ea3894e4d58b986dde946a5
Author: Christian Persch <chpe src gnome org>
Date: Mon Apr 27 20:49:04 2020 +0200
lib: Move fdwalk fallback implementation to its own file
src/meson.build | 1 +
src/missing.cc | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/missing.hh | 5 ++
src/spawn.cc | 33 ++++++++++++-
src/spawn.hh | 1 +
src/vtespawn.cc | 139 ----------------------------------------------------
src/vtespawn.hh | 6 ---
7 files changed, 186 insertions(+), 147 deletions(-)
---
diff --git a/src/meson.build b/src/meson.build
index 5347f125..f25b425d 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -105,6 +105,7 @@ libvte_common_sources = debug_sources + glib_glue_sources + libc_glue_sources +
'color-triple.hh',
'keymap.cc',
'keymap.h',
+ 'missing.cc',
'missing.hh',
'reaper.cc',
'reaper.hh',
diff --git a/src/missing.cc b/src/missing.cc
new file mode 100644
index 00000000..f374a466
--- /dev/null
+++ b/src/missing.cc
@@ -0,0 +1,148 @@
+/*
+ * Copyright © 2020 Christian Persch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+#include <glib-unix.h>
+#include <gio/gio.h>
+
+#ifdef __linux__
+#include <sys/syscall.h> /* for syscall and SYS_getdents64 */
+#endif
+
+#include "missing.hh"
+
+/* BEGIN copied from glib
+ *
+ * Code for fdwalk copied from glib/glib/gspawn.c, there under LGPL2.1+,
+ * and used here under LGPL3+.
+ *
+ * Copyright 2000 Red Hat, Inc.
+ */
+
+#ifndef HAVE_FDWALK
+
+#ifdef __linux__
+
+struct linux_dirent64
+{
+ guint64 d_ino; /* 64-bit inode number */
+ guint64 d_off; /* 64-bit offset to next structure */
+ unsigned short d_reclen; /* Size of this dirent */
+ unsigned char d_type; /* File type */
+ char d_name[]; /* Filename (null-terminated) */
+};
+
+static int
+filename_to_fd (const char *p)
+{
+ char c;
+ int fd = 0;
+ const int cutoff = G_MAXINT / 10;
+ const int cutlim = G_MAXINT % 10;
+
+ if (*p == '\0')
+ return -1;
+
+ while ((c = *p++) != '\0')
+ {
+ if (!g_ascii_isdigit (c))
+ return -1;
+ c -= '0';
+
+ /* Check for overflow. */
+ if (fd > cutoff || (fd == cutoff && c > cutlim))
+ return -1;
+
+ fd = fd * 10 + c;
+ }
+
+ return fd;
+}
+
+#endif /* __linux__ */
+
+int
+fdwalk(int (*cb)(void *data, int fd),
+ void *data)
+{
+ /* Fallback implementation of fdwalk. It should be async-signal safe, but it
+ * may be slow on non-Linux operating systems, especially on systems allowing
+ * very high number of open file descriptors.
+ */
+ int open_max;
+ int fd;
+ int res = 0;
+
+#ifdef HAVE_SYS_RESOURCE_H
+ struct rlimit rl;
+#endif
+
+#ifdef __linux__
+ /* Avoid use of opendir/closedir since these are not async-signal-safe. */
+ int dir_fd = open ("/proc/self/fd", O_RDONLY | O_DIRECTORY | O_CLOEXEC);
+ if (dir_fd >= 0)
+ {
+ char buf[4096];
+ int pos, nread;
+ struct linux_dirent64 *de;
+
+ while ((nread = syscall (SYS_getdents64, dir_fd, buf, sizeof(buf))) > 0)
+ {
+ for (pos = 0; pos < nread; pos += de->d_reclen)
+ {
+ de = (struct linux_dirent64 *)(buf + pos);
+
+ fd = filename_to_fd (de->d_name);
+ if (fd < 0 || fd == dir_fd)
+ continue;
+
+ if ((res = cb (data, fd)) != 0)
+ break;
+ }
+ }
+
+ close (dir_fd);
+ return res;
+ }
+
+ /* If /proc is not mounted or not accessible we fall back to the old
+ * rlimit trick */
+
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H
+
+ if (getrlimit(RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY)
+ open_max = rl.rlim_max;
+ else
+#endif
+ open_max = sysconf (_SC_OPEN_MAX);
+
+ for (fd = 0; fd < open_max; fd++)
+ if ((res = cb (data, fd)) != 0)
+ break;
+
+ return res;
+}
+#endif /* !HAVE_FDWALK */
+
+/* END copied from glib */
diff --git a/src/missing.hh b/src/missing.hh
index 0bff44a4..e0d49c7e 100644
--- a/src/missing.hh
+++ b/src/missing.hh
@@ -23,3 +23,8 @@
#ifndef NSIG
#define NSIG (8 * sizeof(sigset_t))
#endif
+
+#ifndef HAVE_FDWALK
+int fdwalk(int (*cb)(void* data, int fd),
+ void* data);
+#endif
diff --git a/src/spawn.cc b/src/spawn.cc
index 67dea189..b8b78311 100644
--- a/src/spawn.cc
+++ b/src/spawn.cc
@@ -46,8 +46,25 @@
#include "vtedefines.hh"
+#include "missing.hh"
+
namespace vte::base {
+static int
+set_cloexec_cb(void* data,
+ int fd)
+{
+ if (fd >= *reinterpret_cast<int*>(data))
+ return vte::libc::fd_set_cloexec(fd);
+ return 0;
+}
+
+static int
+cloexec_from(int fd)
+{
+ return fdwalk(set_cloexec_cb, &fd);
+}
+
static bool
make_pipe(int flags,
vte::libc::FD& read_fd,
@@ -186,7 +203,8 @@ SpawnContext::exec(vte::libc::FD& child_report_error_pipe_write) noexcept
* child_error_report_pipe_write, which keeps the parent from blocking
* forever on the other end of that pipe.
*/
- _vte_cloexec_from(3);
+ if (cloexec_from(3) < 0)
+ return ExecError::FDWALK;
/* Working directory */
if (m_cwd && chdir(m_cwd.get()) < 0) {
@@ -427,6 +445,10 @@ SpawnOperation::run(vte::glib::Error& error) noexcept
return false;
if (n_read >= 2) {
+ /* Spawn failed. buf[0] contains an error from
+ * SpawnContext::ExecError, and buf[1] contains errno.
+ */
+
/* The process will have called _exit(127) already, no need to kill it */
m_kill_pid = false;
@@ -460,6 +482,12 @@ SpawnOperation::run(vte::glib::Error& error) noexcept
g_strerror(err));
break;
+ case SpawnContext::ExecError::FDWALK:
+ error.set(G_IO_ERROR, g_io_error_from_errno(err),
+ "Failed to fdwalk: %s",
+ g_strerror(err));
+ break;
+
case SpawnContext::ExecError::GETPTPEER:
error.set(G_IO_ERROR, g_io_error_from_errno(err),
"Failed to open PTY peer: %s",
@@ -499,8 +527,9 @@ SpawnOperation::run(vte::glib::Error& error) noexcept
auto arg0 = vte::glib::take_string(g_utf8_make_valid(context().argv()[0], -1));
g_prefix_error(error,
- _("Failed to execute child process “%s”"),
+ _("Failed to execute child process “%s”: "),
arg0.get());
+
return false;
}
diff --git a/src/spawn.hh b/src/spawn.hh
index 26b0ec0b..d2ce5385 100644
--- a/src/spawn.hh
+++ b/src/spawn.hh
@@ -179,6 +179,7 @@ public:
DUP,
DUP2,
EXEC,
+ FDWALK,
GETPTPEER,
SCTTY,
SETSID,
diff --git a/src/vtespawn.cc b/src/vtespawn.cc
index 645600b3..662968be 100644
--- a/src/vtespawn.cc
+++ b/src/vtespawn.cc
@@ -32,17 +32,9 @@
#include <stdlib.h> /* for fdwalk */
#include <dirent.h>
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif /* HAVE_SYS_RESOURCE_H */
-
#include <glib-unix.h>
#include <gio/gio.h>
-#if defined(__linux__) || defined(__DragonFly__)
-#include <sys/syscall.h> /* for syscall and SYS_getdents64 */
-#endif
-
#include "vtespawn.hh"
#include "vteutils.h" /* for strchrnul on non-GNU systems */
#include "reaper.hh"
@@ -81,16 +73,6 @@ _vte_write_err (int fd,
write_all(fd, data, sizeof(data));
}
-static int
-fd_set_cloexec(int fd)
-{
- int flags = fcntl(fd, F_GETFD, 0);
- if (flags < 0)
- return flags;
-
- return fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
-}
-
static int
fd_set_nonblocking(int fd)
{
@@ -102,15 +84,6 @@ fd_set_nonblocking(int fd)
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
-static int
-set_cloexec (void *data, int fd)
-{
- if (fd >= GPOINTER_TO_INT (data))
- fd_set_cloexec (fd);
-
- return 0;
-}
-
G_GNUC_UNUSED static int
close_func (void *data, int fd)
{
@@ -120,118 +93,6 @@ close_func (void *data, int fd)
return 0;
}
-#ifdef __linux__
-struct linux_dirent64
-{
- guint64 d_ino; /* 64-bit inode number */
- guint64 d_off; /* 64-bit offset to next structure */
- unsigned short d_reclen; /* Size of this dirent */
- unsigned char d_type; /* File type */
- char d_name[]; /* Filename (null-terminated) */
-};
-
-static int
-filename_to_fd (const char *p)
-{
- char c;
- int fd = 0;
- const int cutoff = G_MAXINT / 10;
- const int cutlim = G_MAXINT % 10;
-
- if (*p == '\0')
- return -1;
-
- while ((c = *p++) != '\0')
- {
- if (!g_ascii_isdigit (c))
- return -1;
- c -= '0';
-
- /* Check for overflow. */
- if (fd > cutoff || (fd == cutoff && c > cutlim))
- return -1;
-
- fd = fd * 10 + c;
- }
-
- return fd;
-}
-#endif
-
-#ifndef HAVE_FDWALK
-int
-fdwalk (int (*cb)(void *data, int fd), void *data);
-
-int
-fdwalk (int (*cb)(void *data, int fd), void *data)
-{
- /* Fallback implementation of fdwalk. It should be async-signal safe, but it
- * may be slow on non-Linux operating systems, especially on systems allowing
- * very high number of open file descriptors.
- */
- int open_max;
- int fd;
- int res = 0;
-
-#ifdef HAVE_SYS_RESOURCE_H
- struct rlimit rl;
-#endif
-
-#ifdef __linux__
- /* Avoid use of opendir/closedir since these are not async-signal-safe. */
- int dir_fd = open ("/proc/self/fd", O_RDONLY | O_DIRECTORY);
- if (dir_fd >= 0)
- {
- char buf[4096];
- int pos, nread;
- struct linux_dirent64 *de;
-
- while ((nread = syscall (SYS_getdents64, dir_fd, buf, sizeof(buf))) > 0)
- {
- for (pos = 0; pos < nread; pos += de->d_reclen)
- {
- de = (struct linux_dirent64 *)(buf + pos);
-
- fd = filename_to_fd (de->d_name);
- if (fd < 0 || fd == dir_fd)
- continue;
-
- if ((res = cb (data, fd)) != 0)
- break;
- }
- }
-
- close (dir_fd);
- return res;
- }
-
- /* If /proc is not mounted or not accessible we fall back to the old
- * rlimit trick */
-
-#endif
-
-#ifdef HAVE_SYS_RESOURCE_H
-
- if (getrlimit(RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY)
- open_max = rl.rlim_max;
- else
-#endif
- open_max = sysconf (_SC_OPEN_MAX);
-
- for (fd = 0; fd < open_max; fd++)
- if ((res = cb (data, fd)) != 0)
- break;
-
- return res;
-}
-#endif /* HAVE_FDWALK */
-
-void
-_vte_cloexec_from(int fd)
-{
- fdwalk(set_cloexec, GINT_TO_POINTER(fd));
-}
-
bool
_vte_read_ints(int fd,
int* buf,
diff --git a/src/vtespawn.hh b/src/vtespawn.hh
index 855394e6..908fcbe9 100644
--- a/src/vtespawn.hh
+++ b/src/vtespawn.hh
@@ -22,12 +22,6 @@
#include <glib.h>
-void _vte_cloexec_from(int fd);
-
-char** _vte_merge_envv(char** envp,
- char const* cwd,
- bool inherit);
-
int _vte_execute(char const* file,
char** argv,
char** envp,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]