From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2178) id C6F10385B525; Thu, 6 Jul 2023 17:25:43 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C6F10385B525 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1688664343; bh=Ro69PVeLv+CBWM+8OHw8Lir0GLIWzjaU3r3STShdwo8=; h=From:To:Subject:Date:From; b=DENmd6fWvbrC0SjD4Wl3BFl4dHSdbjf1fLhW++YMflKEAFi9gmybhu/Vn3QD37Bcw GNh70gpLSA6PuaGlWusUHvowq9fefes3CHLqHTmsQEqLMZdGk5HqdVonwz3vce3MKH 6OZgHz+zAsUnCaNoQYwR4TrHmPwWBwp9J+g8Son4= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Florian Weimer To: glibc-cvs@sourceware.org Subject: [glibc/fw/bug30619] Test case for bug 30619 X-Act-Checkin: glibc X-Git-Author: Florian Weimer X-Git-Refname: refs/heads/fw/bug30619 X-Git-Oldrev: e18c293af0ece38921ad71fbd76ff8049c3b2d67 X-Git-Newrev: fb45e0aca9d0bf43d3086fc28e9e5bc66fe6500b Message-Id: <20230706172543.C6F10385B525@sourceware.org> Date: Thu, 6 Jul 2023 17:25:43 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=fb45e0aca9d0bf43d3086fc28e9e5bc66fe6500b commit fb45e0aca9d0bf43d3086fc28e9e5bc66fe6500b Author: Florian Weimer Date: Thu Jul 6 19:24:33 2023 +0200 Test case for bug 30619 Diff: --- sysdeps/pthread/Makefile | 9 ++ sysdeps/pthread/tst-thread-dlopen-fork-mod.c | 1 + sysdeps/pthread/tst-thread-dlopen-fork.c | 133 +++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile index 32cf4eb119..38b0a66d3c 100644 --- a/sysdeps/pthread/Makefile +++ b/sysdeps/pthread/Makefile @@ -335,6 +335,7 @@ tests += \ tst-atfork3 \ tst-atfork4 \ tst-create1 \ + tst-thread-dlopen-fork \ tst-fini1 \ tst-pt-tls4 \ # tests @@ -351,6 +352,7 @@ modules-names += \ tst-atfork3mod \ tst-atfork4mod \ tst-create1mod \ + tst-thread-dlopen-fork-mod \ tst-fini1mod \ tst-tls4moda \ tst-tls4modb \ @@ -525,4 +527,11 @@ LDFLAGS-tst-create1 = -Wl,-export-dynamic $(objpfx)tst-create1: $(shared-thread-library) $(objpfx)tst-create1.out: $(objpfx)tst-create1mod.so +# Create multiple shared objects to be used by the test. +tst-thread-dlopen-fork.sos := \ + $(patsubst %,$(objpfx)tst-thread-dlopen-fork-mod-%.so,$(shell seq 0 16)) +$(tst-thread-dlopen-fork.sos): $(objpfx)tst-thread-dlopen-fork-mod.so + cp -f $< $@ +$(objpfx)tst-thread-dlopen-fork.out: $(tst-thread-dlopen-fork.sos) + endif diff --git a/sysdeps/pthread/tst-thread-dlopen-fork-mod.c b/sysdeps/pthread/tst-thread-dlopen-fork-mod.c new file mode 100644 index 0000000000..c219328239 --- /dev/null +++ b/sysdeps/pthread/tst-thread-dlopen-fork-mod.c @@ -0,0 +1 @@ +/* Empty shared object. */ diff --git a/sysdeps/pthread/tst-thread-dlopen-fork.c b/sysdeps/pthread/tst-thread-dlopen-fork.c new file mode 100644 index 0000000000..53d1279b43 --- /dev/null +++ b/sysdeps/pthread/tst-thread-dlopen-fork.c @@ -0,0 +1,133 @@ +/* Test that dlopen works after concurrent fork. + Copyright (C) 2023 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 + . */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Use atomics to make sure that issues with dlopen/fork come from + implementation problems, and not from exposing the handle of a + partially initialized link map after dlopen returned. */ +static void *_Atomic handles[17]; + +/* Set to true if the dlopen thread has exited. */ +static _Atomic bool requested_exit; + +/* Used to start the forking and the dlopen thread at the same time. */ +static pthread_barrier_t barrier; + +/* Returns the file to open for IDX. */ +static char * +dso_name (int idx) +{ + return xasprintf ("tst-thread-dlopen-fork-mod-%d.so", idx); +} + +static void * +forking_thread (void *closure) +{ + xpthread_barrier_wait (&barrier); + int mode = 0; + while (!requested_exit) + { + pid_t pid = xfork (); + if (pid == 0) + { + switch (mode) + { + case 0: + /* Try to open all handles. */ + for (int i = 0; i < array_length (handles); ++i) + { + char *name = dso_name (i); + void *handle = xdlopen (name, RTLD_LAZY); + if (handles[i] != NULL) + TEST_VERIFY (handle == handles[i]); + free (name); + } + mode = 1; + break; + case 1: + /* Try to open all unopened handles. */ + for (int i = 0; i < array_length (handles); ++i) + if (handles[i] == NULL) + { + char *name = dso_name (i); + xdlopen (name, RTLD_LAZY); + free (name); + } + mode = 2; + break; + case 2: + /* Try to close all opened handles. */ + for (int i = 0; i < array_length (handles); ++i) + if (handles[i] != NULL) + xdlclose (handles[i]); + break; + } + _exit (0); + } + int status; + xwaitpid (pid, &status, 0); + TEST_COMPARE (status, 0); + } + return NULL; +} + +static void * +dlopen_thread (void *closure) +{ + xpthread_barrier_wait (&barrier); + srand (1); + for (int i = 0; i <= 1000; ++i) + { + int idx = rand () % array_length (handles); + void *handle = handles[idx]; + if (handle == NULL) + { + char *name = dso_name (idx); + handles[idx] = xdlopen (name, RTLD_LAZY); + free (name); + } + else + { + handles[idx] = NULL; + xdlclose (handle); + } + } + return NULL; +} + +static int +do_test (void) +{ + xpthread_barrier_init (&barrier, NULL, 2); + pthread_t thr_fork = xpthread_create (NULL, forking_thread, NULL); + pthread_t thr_dlopen = xpthread_create (NULL, dlopen_thread, NULL); + xpthread_join (thr_dlopen); + requested_exit = true; + xpthread_join (thr_fork); + return 0; +} + +#include