* [PATCH 2/2] Add a pthread_create deadlock test [BZ #28357]
@ 2021-09-22 7:51 Szabolcs Nagy
2021-10-01 11:41 ` Adhemerval Zanella
0 siblings, 1 reply; 2+ messages in thread
From: Szabolcs Nagy @ 2021-09-22 7:51 UTC (permalink / raw)
To: libc-alpha
Check if locks in ctors or dtors can cause pthread_create to deadlock.
---
sysdeps/pthread/Makefile | 10 ++-
sysdeps/pthread/tst-create1.c | 120 +++++++++++++++++++++++++++++++
sysdeps/pthread/tst-create1mod.c | 41 +++++++++++
3 files changed, 169 insertions(+), 2 deletions(-)
create mode 100644 sysdeps/pthread/tst-create1.c
create mode 100644 sysdeps/pthread/tst-create1mod.c
diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
index 48dba717a1..4a21abdc38 100644
--- a/sysdeps/pthread/Makefile
+++ b/sysdeps/pthread/Makefile
@@ -150,15 +150,17 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx6 tst-cancelx8 tst-cancelx9 \
tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3
ifeq ($(build-shared),yes)
-tests += tst-atfork2 tst-pt-tls4 tst-_res1 tst-fini1
+tests += tst-atfork2 tst-pt-tls4 tst-_res1 tst-fini1 tst-create1
tests-nolibpthread += tst-fini1
endif
modules-names += tst-atfork2mod tst-tls4moda tst-tls4modb \
- tst-_res1mod1 tst-_res1mod2 tst-fini1mod
+ tst-_res1mod1 tst-_res1mod2 tst-fini1mod \
+ tst-create1mod
test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names)))
tst-atfork2mod.so-no-z-defs = yes
+tst-create1mod.so-no-z-defs = yes
ifeq ($(build-shared),yes)
# Build all the modules even when not actually running test programs.
@@ -277,4 +279,8 @@ LDFLAGS-tst-join7mod.so = -Wl,-soname,tst-join7mod.so
CFLAGS-tst-unwind-thread.c += -funwind-tables
+LDFLAGS-tst-create1 = -Wl,-export-dynamic
+$(objpfx)tst-create1: $(shared-thread-library)
+$(objpfx)tst-create1.out: $(objpfx)tst-create1mod.so
+
endif
diff --git a/sysdeps/pthread/tst-create1.c b/sysdeps/pthread/tst-create1.c
new file mode 100644
index 0000000000..44d1c0fc34
--- /dev/null
+++ b/sysdeps/pthread/tst-create1.c
@@ -0,0 +1,120 @@
+/* Verify that pthread_create does not deadlock when ctors take locks.
+ 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 <stdio.h>
+#include <support/xdlfcn.h>
+#include <support/xthread.h>
+
+/*
+Check if ctor and pthread_create deadlocks in
+
+thread 1: dlopen -> ctor -> lock(user_lock)
+thread 2: lock(user_lock) -> pthread_create
+
+or in
+
+thread 1: dlclose -> dtor -> lock(user_lock)
+thread 2: lock(user_lock) -> pthread_create
+*/
+
+static pthread_barrier_t bar_ctor;
+static pthread_barrier_t bar_dtor;
+static pthread_mutex_t user_lock = PTHREAD_MUTEX_INITIALIZER;
+
+void
+ctor (void)
+{
+ xpthread_barrier_wait (&bar_ctor);
+ dprintf (1, "thread 1: in ctor: started.\n");
+ xpthread_mutex_lock (&user_lock);
+ dprintf (1, "thread 1: in ctor: locked user_lock.\n");
+ xpthread_mutex_unlock (&user_lock);
+ dprintf (1, "thread 1: in ctor: unlocked user_lock.\n");
+ dprintf (1, "thread 1: in ctor: done.\n");
+}
+
+void
+dtor (void)
+{
+ xpthread_barrier_wait (&bar_dtor);
+ dprintf (1, "thread 1: in dtor: started.\n");
+ xpthread_mutex_lock (&user_lock);
+ dprintf (1, "thread 1: in dtor: locked user_lock.\n");
+ xpthread_mutex_unlock (&user_lock);
+ dprintf (1, "thread 1: in dtor: unlocked user_lock.\n");
+ dprintf (1, "thread 1: in dtor: done.\n");
+}
+
+static void *
+thread3 (void *a)
+{
+ dprintf (1, "thread 3: started.\n");
+ dprintf (1, "thread 3: done.\n");
+ return 0;
+}
+
+static void *
+thread2 (void *a)
+{
+ pthread_t t3;
+ dprintf (1, "thread 2: started.\n");
+
+ xpthread_mutex_lock (&user_lock);
+ dprintf (1, "thread 2: locked user_lock.\n");
+ xpthread_barrier_wait (&bar_ctor);
+ t3 = xpthread_create (0, thread3, 0);
+ xpthread_mutex_unlock (&user_lock);
+ dprintf (1, "thread 2: unlocked user_lock.\n");
+ xpthread_join (t3);
+
+ xpthread_mutex_lock (&user_lock);
+ dprintf (1, "thread 2: locked user_lock.\n");
+ xpthread_barrier_wait (&bar_dtor);
+ t3 = xpthread_create (0, thread3, 0);
+ xpthread_mutex_unlock (&user_lock);
+ dprintf (1, "thread 2: unlocked user_lock.\n");
+ xpthread_join (t3);
+
+ dprintf (1, "thread 2: done.\n");
+ return 0;
+}
+
+static void
+thread1 (void)
+{
+ dprintf (1, "thread 1: started.\n");
+ xpthread_barrier_init (&bar_ctor, 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);
+ dprintf (1, "thread 1: dlopen done.\n");
+ xdlclose (p);
+ dprintf (1, "thread 1: dlclose done.\n");
+ xpthread_join (t2);
+ dprintf (1, "thread 1: done.\n");
+}
+
+int
+do_test (void)
+{
+ thread1 ();
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-create1mod.c b/sysdeps/pthread/tst-create1mod.c
new file mode 100644
index 0000000000..62c9006961
--- /dev/null
+++ b/sysdeps/pthread/tst-create1mod.c
@@ -0,0 +1,41 @@
+/* Verify that pthread_create does not deadlock when ctors take locks.
+ 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 <stdio.h>
+
+/* Require TLS setup for the module. */
+__thread int tlsvar;
+
+void ctor (void);
+void dtor (void);
+
+static void __attribute__ ((constructor))
+do_init (void)
+{
+ dprintf (1, "constructor started: %d.\n", tlsvar++);
+ ctor ();
+ dprintf (1, "constructor done: %d.\n", tlsvar++);
+}
+
+static void __attribute__ ((destructor))
+do_end (void)
+{
+ dprintf (1, "destructor started: %d.\n", tlsvar++);
+ dtor ();
+ dprintf (1, "destructor done: %d.\n", tlsvar++);
+}
--
2.17.1
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH 2/2] Add a pthread_create deadlock test [BZ #28357]
2021-09-22 7:51 [PATCH 2/2] Add a pthread_create deadlock test [BZ #28357] Szabolcs Nagy
@ 2021-10-01 11:41 ` Adhemerval Zanella
0 siblings, 0 replies; 2+ messages in thread
From: Adhemerval Zanella @ 2021-10-01 11:41 UTC (permalink / raw)
To: libc-alpha, Szabolcs Nagy
On 22/09/2021 04:51, Szabolcs Nagy via Libc-alpha wrote:
> Check if locks in ctors or dtors can cause pthread_create to deadlock.
LGTM with some change below.
I think it would be better to merge with the fix itself.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> ---
> sysdeps/pthread/Makefile | 10 ++-
> sysdeps/pthread/tst-create1.c | 120 +++++++++++++++++++++++++++++++
> sysdeps/pthread/tst-create1mod.c | 41 +++++++++++
> 3 files changed, 169 insertions(+), 2 deletions(-)
> create mode 100644 sysdeps/pthread/tst-create1.c
> create mode 100644 sysdeps/pthread/tst-create1mod.c
>
> diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
> index 48dba717a1..4a21abdc38 100644
> --- a/sysdeps/pthread/Makefile
> +++ b/sysdeps/pthread/Makefile
> @@ -150,15 +150,17 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx6 tst-cancelx8 tst-cancelx9 \
> tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3
>
> ifeq ($(build-shared),yes)
> -tests += tst-atfork2 tst-pt-tls4 tst-_res1 tst-fini1
> +tests += tst-atfork2 tst-pt-tls4 tst-_res1 tst-fini1 tst-create1
> tests-nolibpthread += tst-fini1
> endif
>
> modules-names += tst-atfork2mod tst-tls4moda tst-tls4modb \
> - tst-_res1mod1 tst-_res1mod2 tst-fini1mod
> + tst-_res1mod1 tst-_res1mod2 tst-fini1mod \
> + tst-create1mod
> test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names)))
>
> tst-atfork2mod.so-no-z-defs = yes
> +tst-create1mod.so-no-z-defs = yes
>
> ifeq ($(build-shared),yes)
> # Build all the modules even when not actually running test programs.
> @@ -277,4 +279,8 @@ LDFLAGS-tst-join7mod.so = -Wl,-soname,tst-join7mod.so
>
> CFLAGS-tst-unwind-thread.c += -funwind-tables
>
> +LDFLAGS-tst-create1 = -Wl,-export-dynamic
> +$(objpfx)tst-create1: $(shared-thread-library)
> +$(objpfx)tst-create1.out: $(objpfx)tst-create1mod.so
> +
> endif
Ok.
> diff --git a/sysdeps/pthread/tst-create1.c b/sysdeps/pthread/tst-create1.c
> new file mode 100644
> index 0000000000..44d1c0fc34
> --- /dev/null
> +++ b/sysdeps/pthread/tst-create1.c
> @@ -0,0 +1,120 @@
> +/* Verify that pthread_create does not deadlock when ctors take locks.
> + 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 <stdio.h>
> +#include <support/xdlfcn.h>
> +#include <support/xthread.h>
> +
> +/*
> +Check if ctor and pthread_create deadlocks in
> +
> +thread 1: dlopen -> ctor -> lock(user_lock)
> +thread 2: lock(user_lock) -> pthread_create
> +
> +or in
> +
> +thread 1: dlclose -> dtor -> lock(user_lock)
> +thread 2: lock(user_lock) -> pthread_create
> +*/
> +
> +static pthread_barrier_t bar_ctor;
> +static pthread_barrier_t bar_dtor;
> +static pthread_mutex_t user_lock = PTHREAD_MUTEX_INITIALIZER;
> +
> +void
> +ctor (void)
> +{
> + xpthread_barrier_wait (&bar_ctor);
> + dprintf (1, "thread 1: in ctor: started.\n");
May use STDOUT_FILENO instead?
> + xpthread_mutex_lock (&user_lock);
> + dprintf (1, "thread 1: in ctor: locked user_lock.\n");
> + xpthread_mutex_unlock (&user_lock);
> + dprintf (1, "thread 1: in ctor: unlocked user_lock.\n");
> + dprintf (1, "thread 1: in ctor: done.\n");
> +}
> +
> +void
> +dtor (void)
> +{
> + xpthread_barrier_wait (&bar_dtor);
> + dprintf (1, "thread 1: in dtor: started.\n");
> + xpthread_mutex_lock (&user_lock);
> + dprintf (1, "thread 1: in dtor: locked user_lock.\n");
> + xpthread_mutex_unlock (&user_lock);
> + dprintf (1, "thread 1: in dtor: unlocked user_lock.\n");
> + dprintf (1, "thread 1: in dtor: done.\n");
> +}
> +
> +static void *
> +thread3 (void *a)
> +{
> + dprintf (1, "thread 3: started.\n");
> + dprintf (1, "thread 3: done.\n");
> + return 0;
> +}
> +
> +static void *
> +thread2 (void *a)
> +{
> + pthread_t t3;
> + dprintf (1, "thread 2: started.\n");
> +
> + xpthread_mutex_lock (&user_lock);
> + dprintf (1, "thread 2: locked user_lock.\n");
> + xpthread_barrier_wait (&bar_ctor);
> + t3 = xpthread_create (0, thread3, 0);
> + xpthread_mutex_unlock (&user_lock);
> + dprintf (1, "thread 2: unlocked user_lock.\n");
> + xpthread_join (t3);
> +
> + xpthread_mutex_lock (&user_lock);
> + dprintf (1, "thread 2: locked user_lock.\n");
> + xpthread_barrier_wait (&bar_dtor);
> + t3 = xpthread_create (0, thread3, 0);
> + xpthread_mutex_unlock (&user_lock);
> + dprintf (1, "thread 2: unlocked user_lock.\n");
> + xpthread_join (t3);
> +
> + dprintf (1, "thread 2: done.\n");
> + return 0;
> +}
> +
> +static void
> +thread1 (void)
> +{
> + dprintf (1, "thread 1: started.\n");
> + xpthread_barrier_init (&bar_ctor, 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);
> + dprintf (1, "thread 1: dlopen done.\n");
> + xdlclose (p);
> + dprintf (1, "thread 1: dlclose done.\n");
> + xpthread_join (t2);
> + dprintf (1, "thread 1: done.\n");
> +}
> +
> +int
Use static here as well.
> +do_test (void)
> +{
> + thread1 ();
> + return 0;
> +}
> +
> +#define TEST_FUNCTION do_test ()
> +#include "../test-skeleton.c"
Use #include <support/test-driver.c>.
> diff --git a/sysdeps/pthread/tst-create1mod.c b/sysdeps/pthread/tst-create1mod.c
> new file mode 100644
> index 0000000000..62c9006961
> --- /dev/null
> +++ b/sysdeps/pthread/tst-create1mod.c
> @@ -0,0 +1,41 @@
> +/* Verify that pthread_create does not deadlock when ctors take locks.
> + 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 <stdio.h>
> +
> +/* Require TLS setup for the module. */
> +__thread int tlsvar;
> +
> +void ctor (void);
> +void dtor (void);
> +
> +static void __attribute__ ((constructor))
> +do_init (void)
> +{
> + dprintf (1, "constructor started: %d.\n", tlsvar++);
> + ctor ();
> + dprintf (1, "constructor done: %d.\n", tlsvar++);
> +}
> +
> +static void __attribute__ ((destructor))
> +do_end (void)
> +{
> + dprintf (1, "destructor started: %d.\n", tlsvar++);
> + dtor ();
> + dprintf (1, "destructor done: %d.\n", tlsvar++);
> +}
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2021-10-01 11:41 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-22 7:51 [PATCH 2/2] Add a pthread_create deadlock test [BZ #28357] Szabolcs Nagy
2021-10-01 11:41 ` Adhemerval Zanella
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).