From 45b8e60ac4f8cf9f38699cc9d4f81d5cb4afd00e Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Mon, 22 Jun 2020 13:40:27 +0100 Subject: [PATCH] =?UTF-8?q?gspawn:=20Don=E2=80=99t=20use=20getrlimit()=20o?= =?UTF-8?q?r=20sysconf()=20in=20async-signal-safe=20context?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They’re not safe to call in an async-signal-safe context on Linux. `sysconf()` is safe to call on FreeBSD and OpenBSD (at least), so continue doing that. This will reduce performance in the (already low performance) fallback case where `/proc` is inaccessible to a forked process on Linux, while spawning a subprocess. See `man 7 signal-safety`. Signed-off-by: Philip Withnall Helps: #2140 --- glib/gspawn.c | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/glib/gspawn.c b/glib/gspawn.c index 8dbad9e56..eeb6c3e14 100644 --- a/glib/gspawn.c +++ b/glib/gspawn.c @@ -1218,11 +1218,11 @@ safe_fdwalk (int (*cb)(void *data, int fd), void *data) * may be slow on non-Linux operating systems, especially on systems allowing * very high number of open file descriptors. */ - gint open_max; + gint open_max = -1; gint fd; gint res = 0; -#ifdef HAVE_SYS_RESOURCE_H +#if 0 && defined(HAVE_SYS_RESOURCE_H) struct rlimit rl; #endif @@ -1255,19 +1255,36 @@ safe_fdwalk (int (*cb)(void *data, int fd), void *data) } /* If /proc is not mounted or not accessible we fall back to the old - * rlimit trick. + * rlimit trick. */ + +#endif + +#if 0 && defined(HAVE_SYS_RESOURCE_H) + /* Use getrlimit() function provided by the system if it is known to be + * async-signal safe. * - * FIXME: getrlimit() and sysconf() are not async-signal-safe. */ - + * Currently there are no operating systems known to provide a safe + * implementation, so this section is not used for now. + */ + if (getrlimit (RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY) + open_max = rl.rlim_max; #endif - -#ifdef HAVE_SYS_RESOURCE_H - - if (getrlimit(RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY) - open_max = rl.rlim_max; - else +#if defined(__FreeBSD__) || defined(__OpenBSD__) + /* Use sysconf() function provided by the system if it is known to be + * async-signal safe. + * + * FreeBSD: sysconf() is included in the list of async-signal safe functions + * found in https://man.freebsd.org/sigaction(2). + * + * OpenBSD: sysconf() is included in the list of async-signal safe functions + * found in https://man.openbsd.org/sigaction.2. + */ + if (open_max < 0) + open_max = sysconf (_SC_OPEN_MAX); #endif - open_max = sysconf (_SC_OPEN_MAX); + /* Hardcoded fallback: the default process hard limit in Linux as of 2020 */ + if (open_max < 0) + open_max = 4096; for (fd = 0; fd < open_max; fd++) if ((res = cb (data, fd)) != 0)