!292 fix glibc upstream bug BZ@28260 and nss/tst-nss-files-hosts-long and nptl/tst-create1
Merge pull request !292 from liqingqing_1229/master
This commit is contained in:
commit
8466ecd420
37
Fix-failing-nss-tst-nss-files-hosts-long-with-local-.patch
Normal file
37
Fix-failing-nss-tst-nss-files-hosts-long-with-local-.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From ae925404a10bf0ea63d6e8d41e3821f68b4d776c Mon Sep 17 00:00:00 2001
|
||||
From: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Date: Fri, 3 Sep 2021 00:28:14 +0200
|
||||
Subject: [PATCH] Fix failing nss/tst-nss-files-hosts-long with local resolver
|
||||
|
||||
When a local resolver like unbound is listening on the IPv4 loopback
|
||||
address 127.0.0.1, the nss/tst-nss-files-hosts-long test fails. This is
|
||||
due to:
|
||||
- the default resolver in the absence of resolv.conf being 127.0.0.1
|
||||
- the default DNS NSS database configuration in the absence of
|
||||
nsswitch.conf being 'hosts: dns [!UNAVAIL=return] file'
|
||||
|
||||
This causes the requests for 'test4' and 'test6' to first be sent to the
|
||||
local resolver, which responds with NXDOMAIN in the likely case those
|
||||
records do no exist. In turn that causes the access to /etc/hosts to be
|
||||
skipped, which is the purpose of that test.
|
||||
|
||||
Fix that by providing a simple nsswitch.conf file forcing access to
|
||||
/etc/hosts for that test. I have tested that the only changed result in
|
||||
the testsuite is that test.
|
||||
|
||||
(cherry picked from commit 2738480a4b0866723fb8c633f36bdd34a8767581)
|
||||
---
|
||||
nss/tst-nss-files-hosts-long.root/etc/nsswitch.conf | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
create mode 100644 nss/tst-nss-files-hosts-long.root/etc/nsswitch.conf
|
||||
|
||||
diff --git a/nss/tst-nss-files-hosts-long.root/etc/nsswitch.conf b/nss/tst-nss-files-hosts-long.root/etc/nsswitch.conf
|
||||
new file mode 100644
|
||||
index 0000000..5b0c6a4
|
||||
--- /dev/null
|
||||
+++ b/nss/tst-nss-files-hosts-long.root/etc/nsswitch.conf
|
||||
@@ -0,0 +1 @@
|
||||
+hosts: files
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
212
Use-support_open_dev_null_range-io-tst-closefrom-mis.patch
Normal file
212
Use-support_open_dev_null_range-io-tst-closefrom-mis.patch
Normal file
@ -0,0 +1,212 @@
|
||||
From 772e33411bc730f832f415f93eb3e7c67e4d5488 Mon Sep 17 00:00:00 2001
|
||||
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Tue, 24 Aug 2021 16:15:50 -0300
|
||||
Subject: [PATCH] Use support_open_dev_null_range io/tst-closefrom,
|
||||
misc/tst-close_range, and posix/tst-spawn5 (BZ #28260)
|
||||
|
||||
It ensures a continuous range of file descriptor and avoid hitting
|
||||
the RLIMIT_NOFILE.
|
||||
|
||||
Checked on x86_64-linux-gnu.
|
||||
|
||||
(cherry picked from commit 6b20880b22d1d0fce7e9f506baa6fe2d5c7fcfdc)
|
||||
---
|
||||
io/tst-closefrom.c | 21 ++++++---------------
|
||||
posix/tst-spawn5.c | 13 +------------
|
||||
sysdeps/unix/sysv/linux/tst-close_range.c | 31 ++++++++++---------------------
|
||||
3 files changed, 17 insertions(+), 48 deletions(-)
|
||||
|
||||
diff --git a/io/tst-closefrom.c b/io/tst-closefrom.c
|
||||
index d4c1870..395ec0d 100644
|
||||
--- a/io/tst-closefrom.c
|
||||
+++ b/io/tst-closefrom.c
|
||||
@@ -24,31 +24,22 @@
|
||||
#include <support/check.h>
|
||||
#include <support/descriptors.h>
|
||||
#include <support/xunistd.h>
|
||||
+#include <support/support.h>
|
||||
|
||||
#include <array_length.h>
|
||||
|
||||
#define NFDS 100
|
||||
|
||||
static int
|
||||
-open_multiple_temp_files (void)
|
||||
-{
|
||||
- /* Check if the temporary file descriptor has no no gaps. */
|
||||
- int lowfd = xopen ("/dev/null", O_RDONLY, 0600);
|
||||
- for (int i = 1; i <= NFDS; i++)
|
||||
- TEST_COMPARE (xopen ("/dev/null", O_RDONLY, 0600), lowfd + i);
|
||||
- return lowfd;
|
||||
-}
|
||||
-
|
||||
-static int
|
||||
closefrom_test (void)
|
||||
{
|
||||
struct support_descriptors *descrs = support_descriptors_list ();
|
||||
|
||||
- int lowfd = open_multiple_temp_files ();
|
||||
+ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600);
|
||||
|
||||
- const int maximum_fd = lowfd + NFDS;
|
||||
+ const int maximum_fd = lowfd + NFDS - 1;
|
||||
const int half_fd = lowfd + NFDS / 2;
|
||||
- const int gap = maximum_fd / 4;
|
||||
+ const int gap = lowfd + NFDS / 4;
|
||||
|
||||
/* Close half of the descriptors and check result. */
|
||||
closefrom (half_fd);
|
||||
@@ -58,7 +49,7 @@ closefrom_test (void)
|
||||
TEST_COMPARE (fcntl (i, F_GETFL), -1);
|
||||
TEST_COMPARE (errno, EBADF);
|
||||
}
|
||||
- for (int i = 0; i < half_fd; i++)
|
||||
+ for (int i = lowfd; i < half_fd; i++)
|
||||
TEST_VERIFY (fcntl (i, F_GETFL) > -1);
|
||||
|
||||
/* Create some gaps, close up to a threshold, and check result. */
|
||||
@@ -74,7 +65,7 @@ closefrom_test (void)
|
||||
TEST_COMPARE (fcntl (i, F_GETFL), -1);
|
||||
TEST_COMPARE (errno, EBADF);
|
||||
}
|
||||
- for (int i = 0; i < gap; i++)
|
||||
+ for (int i = lowfd; i < gap; i++)
|
||||
TEST_VERIFY (fcntl (i, F_GETFL) > -1);
|
||||
|
||||
/* Close the remmaining but the last one. */
|
||||
diff --git a/posix/tst-spawn5.c b/posix/tst-spawn5.c
|
||||
index ac66738..a95199a 100644
|
||||
--- a/posix/tst-spawn5.c
|
||||
+++ b/posix/tst-spawn5.c
|
||||
@@ -48,17 +48,6 @@ static int initial_argv_count;
|
||||
#define NFDS 100
|
||||
|
||||
static int
|
||||
-open_multiple_temp_files (void)
|
||||
-{
|
||||
- /* Check if the temporary file descriptor has no no gaps. */
|
||||
- int lowfd = xopen ("/dev/null", O_RDONLY, 0600);
|
||||
- for (int i = 1; i <= NFDS; i++)
|
||||
- TEST_COMPARE (xopen ("/dev/null", O_RDONLY, 0600),
|
||||
- lowfd + i);
|
||||
- return lowfd;
|
||||
-}
|
||||
-
|
||||
-static int
|
||||
parse_fd (const char *str)
|
||||
{
|
||||
char *endptr;
|
||||
@@ -185,7 +174,7 @@ spawn_closefrom_test (posix_spawn_file_actions_t *fa, int lowfd, int highfd,
|
||||
static void
|
||||
do_test_closefrom (void)
|
||||
{
|
||||
- int lowfd = open_multiple_temp_files ();
|
||||
+ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600);
|
||||
const int half_fd = lowfd + NFDS / 2;
|
||||
|
||||
/* Close half of the descriptors and check result. */
|
||||
diff --git a/sysdeps/unix/sysv/linux/tst-close_range.c b/sysdeps/unix/sysv/linux/tst-close_range.c
|
||||
index dccb618..f5069d1 100644
|
||||
--- a/sysdeps/unix/sysv/linux/tst-close_range.c
|
||||
+++ b/sysdeps/unix/sysv/linux/tst-close_range.c
|
||||
@@ -36,23 +36,12 @@
|
||||
|
||||
#define NFDS 100
|
||||
|
||||
-static int
|
||||
-open_multiple_temp_files (void)
|
||||
-{
|
||||
- /* Check if the temporary file descriptor has no no gaps. */
|
||||
- int lowfd = xopen ("/dev/null", O_RDONLY, 0600);
|
||||
- for (int i = 1; i <= NFDS; i++)
|
||||
- TEST_COMPARE (xopen ("/dev/null", O_RDONLY, 0600),
|
||||
- lowfd + i);
|
||||
- return lowfd;
|
||||
-}
|
||||
-
|
||||
static void
|
||||
close_range_test_max_upper_limit (void)
|
||||
{
|
||||
struct support_descriptors *descrs = support_descriptors_list ();
|
||||
|
||||
- int lowfd = open_multiple_temp_files ();
|
||||
+ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600);
|
||||
|
||||
{
|
||||
int r = close_range (lowfd, ~0U, 0);
|
||||
@@ -68,7 +57,7 @@ close_range_test_max_upper_limit (void)
|
||||
static void
|
||||
close_range_test_common (int lowfd, unsigned int flags)
|
||||
{
|
||||
- const int maximum_fd = lowfd + NFDS;
|
||||
+ const int maximum_fd = lowfd + NFDS - 1;
|
||||
const int half_fd = lowfd + NFDS / 2;
|
||||
const int gap_1 = maximum_fd - 8;
|
||||
|
||||
@@ -121,7 +110,7 @@ close_range_test (void)
|
||||
struct support_descriptors *descrs = support_descriptors_list ();
|
||||
|
||||
/* Check if the temporary file descriptor has no no gaps. */
|
||||
- int lowfd = open_multiple_temp_files ();
|
||||
+ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600);
|
||||
|
||||
close_range_test_common (lowfd, 0);
|
||||
|
||||
@@ -146,7 +135,7 @@ close_range_test_subprocess (void)
|
||||
struct support_descriptors *descrs = support_descriptors_list ();
|
||||
|
||||
/* Check if the temporary file descriptor has no no gaps. */
|
||||
- int lowfd = open_multiple_temp_files ();
|
||||
+ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600);
|
||||
|
||||
struct support_stack stack = support_stack_alloc (4096);
|
||||
|
||||
@@ -184,7 +173,7 @@ close_range_unshare_test (void)
|
||||
struct support_descriptors *descrs1 = support_descriptors_list ();
|
||||
|
||||
/* Check if the temporary file descriptor has no no gaps. */
|
||||
- int lowfd = open_multiple_temp_files ();
|
||||
+ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600);
|
||||
|
||||
struct support_descriptors *descrs2 = support_descriptors_list ();
|
||||
|
||||
@@ -200,7 +189,7 @@ close_range_unshare_test (void)
|
||||
|
||||
support_stack_free (&stack);
|
||||
|
||||
- for (int i = 0; i < NFDS; i++)
|
||||
+ for (int i = lowfd; i < lowfd + NFDS; i++)
|
||||
TEST_VERIFY (fcntl (i, F_GETFL) > -1);
|
||||
|
||||
support_descriptors_check (descrs2);
|
||||
@@ -226,9 +215,9 @@ static void
|
||||
close_range_cloexec_test (void)
|
||||
{
|
||||
/* Check if the temporary file descriptor has no no gaps. */
|
||||
- const int lowfd = open_multiple_temp_files ();
|
||||
+ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600);
|
||||
|
||||
- const int maximum_fd = lowfd + NFDS;
|
||||
+ const int maximum_fd = lowfd + NFDS - 1;
|
||||
const int half_fd = lowfd + NFDS / 2;
|
||||
const int gap_1 = maximum_fd - 8;
|
||||
|
||||
@@ -251,13 +240,13 @@ close_range_cloexec_test (void)
|
||||
/* Create some gaps, close up to a threshold, and check result. */
|
||||
static int gap_close[] = { 57, 78, 81, 82, 84, 90 };
|
||||
for (int i = 0; i < array_length (gap_close); i++)
|
||||
- xclose (gap_close[i]);
|
||||
+ xclose (lowfd + gap_close[i]);
|
||||
|
||||
TEST_COMPARE (close_range (half_fd + 1, gap_1, CLOSE_RANGE_CLOEXEC), 0);
|
||||
for (int i = half_fd + 1; i < gap_1; i++)
|
||||
{
|
||||
int flags = fcntl (i, F_GETFD);
|
||||
- if (is_in_array (gap_close, array_length (gap_close), i))
|
||||
+ if (is_in_array (gap_close, array_length (gap_close), i - lowfd))
|
||||
TEST_COMPARE (flags, -1);
|
||||
else
|
||||
{
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
11
glibc.spec
11
glibc.spec
@ -65,7 +65,7 @@
|
||||
##############################################################################
|
||||
Name: glibc
|
||||
Version: 2.34
|
||||
Release: 33
|
||||
Release: 34
|
||||
Summary: The GNU libc libraries
|
||||
License: %{all_license}
|
||||
URL: http://www.gnu.org/software/glibc/
|
||||
@ -138,6 +138,10 @@ Patch51: linux-Simplify-get_nprocs.patch
|
||||
Patch52: misc-Add-__get_nprocs_sched.patch
|
||||
Patch53: linux-Revert-the-use-of-sched_getaffinity-on-get_npr.patch
|
||||
Patch54: pthread-tst-cancel28-Fix-barrier-re-init-race-condit.patch
|
||||
Patch55: support-Add-support_open_dev_null_range.patch
|
||||
Patch56: Use-support_open_dev_null_range-io-tst-closefrom-mis.patch
|
||||
Patch57: Fix-failing-nss-tst-nss-files-hosts-long-with-local-.patch
|
||||
Patch58: nptl-Add-one-more-barrier-to-nptl-tst-create1.patch
|
||||
|
||||
Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch
|
||||
Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch
|
||||
@ -1334,6 +1338,11 @@ fi
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Tue Dec 21 2021 Qingqing Li <liqingqing3@huawei.com> - 2.34-34
|
||||
- tst: fix failing nss/tst-nss-files-hosts-long with local resolver
|
||||
use support_open_dev_null_range io/tst-closefrom, mise/tst-close_range, and posix/tst-spawn5(BZ#28260)
|
||||
nptl: add one more barrier to nptl/tst-create1
|
||||
|
||||
* Wed Dec 15 2021 Qingqing Li <liqingqing3@huawei.com> - 2.34-33
|
||||
- pthread/tst-cancel28: Fix barrier re-init race condition
|
||||
|
||||
|
||||
67
nptl-Add-one-more-barrier-to-nptl-tst-create1.patch
Normal file
67
nptl-Add-one-more-barrier-to-nptl-tst-create1.patch
Normal file
@ -0,0 +1,67 @@
|
||||
From 5cc338565479a620244c2f8ff35956629c4dbf81 Mon Sep 17 00:00:00 2001
|
||||
From: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri, 10 Dec 2021 05:14:24 +0100
|
||||
Subject: [PATCH] nptl: Add one more barrier to nptl/tst-create1
|
||||
|
||||
Without the bar_ctor_finish barrier, it was possible that thread2
|
||||
re-locked user_lock before ctor had a chance to lock it. ctor then
|
||||
blocked in its locking operation, xdlopen from the main thread
|
||||
did not return, and thread2 was stuck waiting in bar_dtor:
|
||||
|
||||
thread 1: started.
|
||||
thread 2: started.
|
||||
thread 2: locked user_lock.
|
||||
constructor started: 0.
|
||||
thread 1: in ctor: started.
|
||||
thread 3: started.
|
||||
thread 3: done.
|
||||
thread 2: unlocked user_lock.
|
||||
thread 2: locked user_lock.
|
||||
|
||||
Fixes the test in commit 83b5323261bb72313bffcf37476c1b8f0847c736
|
||||
("elf: Avoid deadlock between pthread_create and ctors [BZ #28357]").
|
||||
|
||||
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
---
|
||||
sysdeps/pthread/tst-create1.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/sysdeps/pthread/tst-create1.c b/sysdeps/pthread/tst-create1.c
|
||||
index 932586c..763ded8 100644
|
||||
--- a/sysdeps/pthread/tst-create1.c
|
||||
+++ b/sysdeps/pthread/tst-create1.c
|
||||
@@ -33,6 +33,7 @@ thread 2: lock(user_lock) -> pthread_create
|
||||
*/
|
||||
|
||||
static pthread_barrier_t bar_ctor;
|
||||
+static pthread_barrier_t bar_ctor_finish;
|
||||
static pthread_barrier_t bar_dtor;
|
||||
static pthread_mutex_t user_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
@@ -46,6 +47,7 @@ ctor (void)
|
||||
xpthread_mutex_unlock (&user_lock);
|
||||
dprintf (1, "thread 1: in ctor: unlocked user_lock.\n");
|
||||
dprintf (1, "thread 1: in ctor: done.\n");
|
||||
+ xpthread_barrier_wait (&bar_ctor_finish);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -81,6 +83,7 @@ thread2 (void *a)
|
||||
xpthread_mutex_unlock (&user_lock);
|
||||
dprintf (1, "thread 2: unlocked user_lock.\n");
|
||||
xpthread_join (t3);
|
||||
+ xpthread_barrier_wait (&bar_ctor_finish);
|
||||
|
||||
xpthread_mutex_lock (&user_lock);
|
||||
dprintf (1, "thread 2: locked user_lock.\n");
|
||||
@@ -99,6 +102,7 @@ thread1 (void)
|
||||
{
|
||||
dprintf (1, "thread 1: started.\n");
|
||||
xpthread_barrier_init (&bar_ctor, NULL, 2);
|
||||
+ xpthread_barrier_init (&bar_ctor_finish, NULL, 2);
|
||||
xpthread_barrier_init (&bar_dtor, NULL, 2);
|
||||
pthread_t t2 = xpthread_create (0, thread2, 0);
|
||||
void *p = xdlopen ("tst-create1mod.so", RTLD_NOW | RTLD_GLOBAL);
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
363
support-Add-support_open_dev_null_range.patch
Normal file
363
support-Add-support_open_dev_null_range.patch
Normal file
@ -0,0 +1,363 @@
|
||||
From e814f4b04ee413a7bb3dfa43e74c8fb4abf58359 Mon Sep 17 00:00:00 2001
|
||||
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Tue, 24 Aug 2021 16:12:24 -0300
|
||||
Subject: [PATCH] support: Add support_open_dev_null_range
|
||||
|
||||
It returns a range of file descriptor referring to the '/dev/null'
|
||||
pathname. The function takes care of restarting the open range
|
||||
if a file descriptor is found within the specified range and
|
||||
also increases RLIMIT_NOFILE if required.
|
||||
|
||||
Checked on x86_64-linux-gnu.
|
||||
---
|
||||
support/Makefile | 2 +
|
||||
support/support-open-dev-null-range.c | 134 ++++++++++++++++++++++++++
|
||||
support/support.h | 8 ++
|
||||
support/tst-support-open-dev-null-range.c | 155 ++++++++++++++++++++++++++++++
|
||||
4 files changed, 299 insertions(+)
|
||||
create mode 100644 support/support-open-dev-null-range.c
|
||||
create mode 100644 support/tst-support-open-dev-null-range.c
|
||||
|
||||
diff --git a/support/Makefile b/support/Makefile
|
||||
index a462781..6332e7b 100644
|
||||
--- a/support/Makefile
|
||||
+++ b/support/Makefile
|
||||
@@ -66,6 +66,7 @@ libsupport-routines = \
|
||||
support_path_support_time64 \
|
||||
support_process_state \
|
||||
support_ptrace \
|
||||
+ support-open-dev-null-range \
|
||||
support_openpty \
|
||||
support_paths \
|
||||
support_quote_blob \
|
||||
@@ -264,6 +265,7 @@ tests = \
|
||||
tst-support_capture_subprocess \
|
||||
tst-support_descriptors \
|
||||
tst-support_format_dns_packet \
|
||||
+ tst-support-open-dev-null-range \
|
||||
tst-support-process_state \
|
||||
tst-support_quote_blob \
|
||||
tst-support_quote_string \
|
||||
diff --git a/support/support-open-dev-null-range.c b/support/support-open-dev-null-range.c
|
||||
new file mode 100644
|
||||
index 0000000..80d9dba
|
||||
--- /dev/null
|
||||
+++ b/support/support-open-dev-null-range.c
|
||||
@@ -0,0 +1,134 @@
|
||||
+/* Return a range of open file descriptors.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C 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 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C 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 Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/xunistd.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <sys/resource.h>
|
||||
+
|
||||
+static void
|
||||
+increase_nofile (void)
|
||||
+{
|
||||
+ struct rlimit rl;
|
||||
+ if (getrlimit (RLIMIT_NOFILE, &rl) == -1)
|
||||
+ FAIL_EXIT1 ("getrlimit (RLIMIT_NOFILE): %m");
|
||||
+
|
||||
+ rl.rlim_cur += 128;
|
||||
+
|
||||
+ if (setrlimit (RLIMIT_NOFILE, &rl) == 1)
|
||||
+ FAIL_EXIT1 ("setrlimit (RLIMIT_NOFILE): %m");
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+open_dev_null (int flags, mode_t mode)
|
||||
+{
|
||||
+ int fd = open64 ("/dev/null", flags, mode);
|
||||
+ if (fd > 0)
|
||||
+ return fd;
|
||||
+
|
||||
+ if (fd < 0 && errno != EMFILE)
|
||||
+ FAIL_EXIT1 ("open64 (\"/dev/null\", 0x%x, 0%o): %m", flags, mode);
|
||||
+
|
||||
+ increase_nofile ();
|
||||
+
|
||||
+ return xopen ("/dev/null", flags, mode);
|
||||
+}
|
||||
+
|
||||
+struct range
|
||||
+{
|
||||
+ int lowfd;
|
||||
+ size_t len;
|
||||
+};
|
||||
+
|
||||
+struct range_list
|
||||
+{
|
||||
+ size_t total;
|
||||
+ size_t used;
|
||||
+ struct range *ranges;
|
||||
+};
|
||||
+
|
||||
+static void
|
||||
+range_init (struct range_list *r)
|
||||
+{
|
||||
+ r->total = 8;
|
||||
+ r->used = 0;
|
||||
+ r->ranges = xmalloc (r->total * sizeof (struct range));
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+range_add (struct range_list *r, int lowfd, size_t len)
|
||||
+{
|
||||
+ if (r->used == r->total)
|
||||
+ {
|
||||
+ r->total *= 2;
|
||||
+ r->ranges = xrealloc (r->ranges, r->total * sizeof (struct range));
|
||||
+ }
|
||||
+ r->ranges[r->used].lowfd = lowfd;
|
||||
+ r->ranges[r->used].len = len;
|
||||
+ r->used++;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+range_close (struct range_list *r)
|
||||
+{
|
||||
+ for (size_t i = 0; i < r->used; i++)
|
||||
+ {
|
||||
+ int minfd = r->ranges[i].lowfd;
|
||||
+ int maxfd = r->ranges[i].lowfd + r->ranges[i].len;
|
||||
+ for (int fd = minfd; fd < maxfd; fd++)
|
||||
+ xclose (fd);
|
||||
+ }
|
||||
+ free (r->ranges);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+support_open_dev_null_range (int num, int flags, mode_t mode)
|
||||
+{
|
||||
+ /* We keep track of the ranges that hit an already opened descriptor, so
|
||||
+ we close them after we get a working range. */
|
||||
+ struct range_list rl;
|
||||
+ range_init (&rl);
|
||||
+
|
||||
+ int lowfd = open_dev_null (flags, mode);
|
||||
+ int prevfd = lowfd;
|
||||
+ while (true)
|
||||
+ {
|
||||
+ int i = 1;
|
||||
+ for (; i < num; i++)
|
||||
+ {
|
||||
+ int fd = open_dev_null (flags, mode);
|
||||
+ if (fd != lowfd + i)
|
||||
+ {
|
||||
+ range_add (&rl, lowfd, prevfd - lowfd + 1);
|
||||
+
|
||||
+ prevfd = lowfd = fd;
|
||||
+ break;
|
||||
+ }
|
||||
+ prevfd = fd;
|
||||
+ }
|
||||
+ if (i == num)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ range_close (&rl);
|
||||
+
|
||||
+ return lowfd;
|
||||
+}
|
||||
diff --git a/support/support.h b/support/support.h
|
||||
index 834dba9..e6911e1 100644
|
||||
--- a/support/support.h
|
||||
+++ b/support/support.h
|
||||
@@ -193,6 +193,14 @@ struct support_stack support_stack_alloc (size_t size);
|
||||
/* Deallocate the STACK. */
|
||||
void support_stack_free (struct support_stack *stack);
|
||||
|
||||
+
|
||||
+/* Create a range of NUM opened '/dev/null' file descriptors using FLAGS and
|
||||
+ MODE. The function takes care of restarting the open range if a file
|
||||
+ descriptor is found within the specified range and also increases
|
||||
+ RLIMIT_NOFILE if required.
|
||||
+ The returned value is the lowest file descriptor number. */
|
||||
+int support_open_dev_null_range (int num, int flags, mode_t mode);
|
||||
+
|
||||
__END_DECLS
|
||||
|
||||
#endif /* SUPPORT_H */
|
||||
diff --git a/support/tst-support-open-dev-null-range.c b/support/tst-support-open-dev-null-range.c
|
||||
new file mode 100644
|
||||
index 0000000..8e29def
|
||||
--- /dev/null
|
||||
+++ b/support/tst-support-open-dev-null-range.c
|
||||
@@ -0,0 +1,155 @@
|
||||
+/* Tests for support_open_dev_null_range.
|
||||
+ Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C 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 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C 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 Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <dirent.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <limits.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/xunistd.h>
|
||||
+#include <sys/resource.h>
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+#ifndef PATH_MAX
|
||||
+# define PATH_MAX 1024
|
||||
+#endif
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+static void
|
||||
+check_path (int fd)
|
||||
+{
|
||||
+ char *proc_fd_path = xasprintf ("/proc/self/fd/%d", fd);
|
||||
+ char file_path[PATH_MAX];
|
||||
+ ssize_t file_path_length
|
||||
+ = readlink (proc_fd_path, file_path, sizeof (file_path));
|
||||
+ free (proc_fd_path);
|
||||
+ if (file_path_length < 0)
|
||||
+ FAIL_EXIT1 ("readlink (%s, %p, %zu)", proc_fd_path, file_path,
|
||||
+ sizeof (file_path));
|
||||
+ file_path[file_path_length] = '\0';
|
||||
+ TEST_COMPARE_STRING (file_path, "/dev/null");
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+number_of_opened_files (void)
|
||||
+{
|
||||
+ DIR *fds = opendir ("/proc/self/fd");
|
||||
+ if (fds == NULL)
|
||||
+ FAIL_EXIT1 ("opendir (\"/proc/self/fd\"): %m");
|
||||
+
|
||||
+ int r = 0;
|
||||
+ while (true)
|
||||
+ {
|
||||
+ errno = 0;
|
||||
+ struct dirent64 *e = readdir64 (fds);
|
||||
+ if (e == NULL)
|
||||
+ {
|
||||
+ if (errno != 0)
|
||||
+ FAIL_EXIT1 ("readdir: %m");
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (e->d_name[0] == '.')
|
||||
+ continue;
|
||||
+
|
||||
+ char *endptr;
|
||||
+ long int fd = strtol (e->d_name, &endptr, 10);
|
||||
+ if (*endptr != '\0' || fd < 0 || fd > INT_MAX)
|
||||
+ FAIL_EXIT1 ("readdir: invalid file descriptor name: /proc/self/fd/%s",
|
||||
+ e->d_name);
|
||||
+
|
||||
+ /* Skip the descriptor which is used to enumerate the
|
||||
+ descriptors. */
|
||||
+ if (fd == dirfd (fds))
|
||||
+ continue;
|
||||
+
|
||||
+ r = r + 1;
|
||||
+ }
|
||||
+
|
||||
+ closedir (fds);
|
||||
+
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ const int nfds1 = 8;
|
||||
+ int lowfd = support_open_dev_null_range (nfds1, O_RDONLY, 0600);
|
||||
+ for (int i = 0; i < nfds1; i++)
|
||||
+ {
|
||||
+ TEST_VERIFY (fcntl (lowfd + i, F_GETFL) > -1);
|
||||
+ check_path (lowfd + i);
|
||||
+ }
|
||||
+
|
||||
+ /* create some gaps. */
|
||||
+ xclose (lowfd + 1);
|
||||
+ xclose (lowfd + 5);
|
||||
+ xclose (lowfd + 6);
|
||||
+
|
||||
+ const int nfds2 = 16;
|
||||
+ int lowfd2 = support_open_dev_null_range (nfds2, O_RDONLY, 0600);
|
||||
+ for (int i = 0; i < nfds2; i++)
|
||||
+ {
|
||||
+ TEST_VERIFY (fcntl (lowfd2 + i, F_GETFL) > -1);
|
||||
+ check_path (lowfd2 + i);
|
||||
+ }
|
||||
+
|
||||
+ /* Decrease the maximum number of files. */
|
||||
+ {
|
||||
+ struct rlimit rl;
|
||||
+ if (getrlimit (RLIMIT_NOFILE, &rl) == -1)
|
||||
+ FAIL_EXIT1 ("getrlimit (RLIMIT_NOFILE): %m");
|
||||
+
|
||||
+ rl.rlim_cur = number_of_opened_files ();
|
||||
+
|
||||
+ if (setrlimit (RLIMIT_NOFILE, &rl) == 1)
|
||||
+ FAIL_EXIT1 ("setrlimit (RLIMIT_NOFILE): %m");
|
||||
+ }
|
||||
+
|
||||
+ const int nfds3 = 16;
|
||||
+ int lowfd3 = support_open_dev_null_range (nfds3, O_RDONLY, 0600);
|
||||
+ for (int i = 0; i < nfds3; i++)
|
||||
+ {
|
||||
+ TEST_VERIFY (fcntl (lowfd3 + i, F_GETFL) > -1);
|
||||
+ check_path (lowfd3 + i);
|
||||
+ }
|
||||
+
|
||||
+ /* create a lot of gaps to trigger the range extension. */
|
||||
+ xclose (lowfd3 + 1);
|
||||
+ xclose (lowfd3 + 3);
|
||||
+ xclose (lowfd3 + 5);
|
||||
+ xclose (lowfd3 + 7);
|
||||
+ xclose (lowfd3 + 9);
|
||||
+ xclose (lowfd3 + 11);
|
||||
+ xclose (lowfd3 + 13);
|
||||
+
|
||||
+ const int nfds4 = 16;
|
||||
+ int lowfd4 = support_open_dev_null_range (nfds4, O_RDONLY, 0600);
|
||||
+ for (int i = 0; i < nfds4; i++)
|
||||
+ {
|
||||
+ TEST_VERIFY (fcntl (lowfd4 + i, F_GETFL) > -1);
|
||||
+ check_path (lowfd4 + i);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user