forked from pool/glibc
Accepting request 318958 from home:Andreas_Schwab:Factory
- pthread-join-deadlock.patch: Use IE model for static variables in libc.so, libpthread.so and rtld (bsc#930015, BZ #18457) OBS-URL: https://build.opensuse.org/request/show/318958 OBS-URL: https://build.opensuse.org/package/show/Base:System/glibc?expand=0&rev=409
This commit is contained in:
parent
0353781f37
commit
f26bd5d9b4
@ -1,3 +1,9 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Mon Jul 27 09:08:21 UTC 2015 - schwab@suse.de
|
||||||
|
|
||||||
|
- pthread-join-deadlock.patch: Use IE model for static variables in
|
||||||
|
libc.so, libpthread.so and rtld (bsc#930015, BZ #18457)
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Wed Jul 22 09:13:48 UTC 2015 - schwab@suse.de
|
Wed Jul 22 09:13:48 UTC 2015 - schwab@suse.de
|
||||||
|
|
||||||
|
@ -251,6 +251,8 @@ Patch1008: nss-separate-state-getXXent.patch
|
|||||||
Patch1009: aarch64-sigstksz.patch
|
Patch1009: aarch64-sigstksz.patch
|
||||||
# PATCH-FIX-UPSTREAM malloc: Do not corrupt the top of a threaded heap if top chunk is MINSIZE (BZ #18502)
|
# PATCH-FIX-UPSTREAM malloc: Do not corrupt the top of a threaded heap if top chunk is MINSIZE (BZ #18502)
|
||||||
Patch1010: heap-top-corruption.patch
|
Patch1010: heap-top-corruption.patch
|
||||||
|
# PATCH-FIX-UPSTREAM Use IE model for static variables in libc.so, libpthread.so and rtld (BZ #18457)
|
||||||
|
Patch1011: pthread-join-deadlock.patch
|
||||||
|
|
||||||
###
|
###
|
||||||
# Patches awaiting upstream approval
|
# Patches awaiting upstream approval
|
||||||
@ -265,8 +267,6 @@ Patch2003: abort-no-flush.patch
|
|||||||
Patch2005: glibc-memset-nontemporal.diff
|
Patch2005: glibc-memset-nontemporal.diff
|
||||||
# PATCH-FIX-UPSTREAM Avoid redundant shift character in iconv output at block boundary (BZ #17197)
|
# PATCH-FIX-UPSTREAM Avoid redundant shift character in iconv output at block boundary (BZ #17197)
|
||||||
Patch2006: ibm93x-redundant-shift-si.patch
|
Patch2006: ibm93x-redundant-shift-si.patch
|
||||||
# PATCH-FIX-UPSTREAM Don't require rtld lock to store static TLS offset in the DTV (BZ #18457)
|
|
||||||
Patch2007: pthread-join-deadlock.patch
|
|
||||||
|
|
||||||
# Non-glibc patches
|
# Non-glibc patches
|
||||||
# PATCH-FIX-OPENSUSE Remove debianisms from manpages
|
# PATCH-FIX-OPENSUSE Remove debianisms from manpages
|
||||||
@ -477,13 +477,13 @@ rm nscd/s-stamp
|
|||||||
%patch1008 -p1
|
%patch1008 -p1
|
||||||
%patch1009 -p1
|
%patch1009 -p1
|
||||||
%patch1010 -p1
|
%patch1010 -p1
|
||||||
|
%patch1011 -p1
|
||||||
|
|
||||||
%patch2000 -p1
|
%patch2000 -p1
|
||||||
%patch2002 -p1
|
%patch2002 -p1
|
||||||
%patch2003 -p1
|
%patch2003 -p1
|
||||||
%patch2005 -p1
|
%patch2005 -p1
|
||||||
%patch2006 -p1
|
%patch2006 -p1
|
||||||
%patch2007 -p1
|
|
||||||
|
|
||||||
%patch3000
|
%patch3000
|
||||||
|
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Mon Jul 27 09:08:21 UTC 2015 - schwab@suse.de
|
||||||
|
|
||||||
|
- pthread-join-deadlock.patch: Use IE model for static variables in
|
||||||
|
libc.so, libpthread.so and rtld (bsc#930015, BZ #18457)
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Wed Jul 22 09:13:48 UTC 2015 - schwab@suse.de
|
Wed Jul 22 09:13:48 UTC 2015 - schwab@suse.de
|
||||||
|
|
||||||
|
@ -250,6 +250,8 @@ Patch1008: nss-separate-state-getXXent.patch
|
|||||||
Patch1009: aarch64-sigstksz.patch
|
Patch1009: aarch64-sigstksz.patch
|
||||||
# PATCH-FIX-UPSTREAM malloc: Do not corrupt the top of a threaded heap if top chunk is MINSIZE (BZ #18502)
|
# PATCH-FIX-UPSTREAM malloc: Do not corrupt the top of a threaded heap if top chunk is MINSIZE (BZ #18502)
|
||||||
Patch1010: heap-top-corruption.patch
|
Patch1010: heap-top-corruption.patch
|
||||||
|
# PATCH-FIX-UPSTREAM Use IE model for static variables in libc.so, libpthread.so and rtld (BZ #18457)
|
||||||
|
Patch1011: pthread-join-deadlock.patch
|
||||||
|
|
||||||
###
|
###
|
||||||
# Patches awaiting upstream approval
|
# Patches awaiting upstream approval
|
||||||
@ -264,8 +266,6 @@ Patch2003: abort-no-flush.patch
|
|||||||
Patch2005: glibc-memset-nontemporal.diff
|
Patch2005: glibc-memset-nontemporal.diff
|
||||||
# PATCH-FIX-UPSTREAM Avoid redundant shift character in iconv output at block boundary (BZ #17197)
|
# PATCH-FIX-UPSTREAM Avoid redundant shift character in iconv output at block boundary (BZ #17197)
|
||||||
Patch2006: ibm93x-redundant-shift-si.patch
|
Patch2006: ibm93x-redundant-shift-si.patch
|
||||||
# PATCH-FIX-UPSTREAM Don't require rtld lock to store static TLS offset in the DTV (BZ #18457)
|
|
||||||
Patch2007: pthread-join-deadlock.patch
|
|
||||||
|
|
||||||
# Non-glibc patches
|
# Non-glibc patches
|
||||||
# PATCH-FIX-OPENSUSE Remove debianisms from manpages
|
# PATCH-FIX-OPENSUSE Remove debianisms from manpages
|
||||||
@ -477,13 +477,13 @@ rm nscd/s-stamp
|
|||||||
%patch1008 -p1
|
%patch1008 -p1
|
||||||
%patch1009 -p1
|
%patch1009 -p1
|
||||||
%patch1010 -p1
|
%patch1010 -p1
|
||||||
|
%patch1011 -p1
|
||||||
|
|
||||||
%patch2000 -p1
|
%patch2000 -p1
|
||||||
%patch2002 -p1
|
%patch2002 -p1
|
||||||
%patch2003 -p1
|
%patch2003 -p1
|
||||||
%patch2005 -p1
|
%patch2005 -p1
|
||||||
%patch2006 -p1
|
%patch2006 -p1
|
||||||
%patch2007 -p1
|
|
||||||
|
|
||||||
%patch3000
|
%patch3000
|
||||||
|
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Mon Jul 27 09:08:21 UTC 2015 - schwab@suse.de
|
||||||
|
|
||||||
|
- pthread-join-deadlock.patch: Use IE model for static variables in
|
||||||
|
libc.so, libpthread.so and rtld (bsc#930015, BZ #18457)
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Wed Jul 22 09:13:48 UTC 2015 - schwab@suse.de
|
Wed Jul 22 09:13:48 UTC 2015 - schwab@suse.de
|
||||||
|
|
||||||
|
@ -251,6 +251,8 @@ Patch1008: nss-separate-state-getXXent.patch
|
|||||||
Patch1009: aarch64-sigstksz.patch
|
Patch1009: aarch64-sigstksz.patch
|
||||||
# PATCH-FIX-UPSTREAM malloc: Do not corrupt the top of a threaded heap if top chunk is MINSIZE (BZ #18502)
|
# PATCH-FIX-UPSTREAM malloc: Do not corrupt the top of a threaded heap if top chunk is MINSIZE (BZ #18502)
|
||||||
Patch1010: heap-top-corruption.patch
|
Patch1010: heap-top-corruption.patch
|
||||||
|
# PATCH-FIX-UPSTREAM Use IE model for static variables in libc.so, libpthread.so and rtld (BZ #18457)
|
||||||
|
Patch1011: pthread-join-deadlock.patch
|
||||||
|
|
||||||
###
|
###
|
||||||
# Patches awaiting upstream approval
|
# Patches awaiting upstream approval
|
||||||
@ -265,8 +267,6 @@ Patch2003: abort-no-flush.patch
|
|||||||
Patch2005: glibc-memset-nontemporal.diff
|
Patch2005: glibc-memset-nontemporal.diff
|
||||||
# PATCH-FIX-UPSTREAM Avoid redundant shift character in iconv output at block boundary (BZ #17197)
|
# PATCH-FIX-UPSTREAM Avoid redundant shift character in iconv output at block boundary (BZ #17197)
|
||||||
Patch2006: ibm93x-redundant-shift-si.patch
|
Patch2006: ibm93x-redundant-shift-si.patch
|
||||||
# PATCH-FIX-UPSTREAM Don't require rtld lock to store static TLS offset in the DTV (BZ #18457)
|
|
||||||
Patch2007: pthread-join-deadlock.patch
|
|
||||||
|
|
||||||
# Non-glibc patches
|
# Non-glibc patches
|
||||||
# PATCH-FIX-OPENSUSE Remove debianisms from manpages
|
# PATCH-FIX-OPENSUSE Remove debianisms from manpages
|
||||||
@ -477,13 +477,13 @@ rm nscd/s-stamp
|
|||||||
%patch1008 -p1
|
%patch1008 -p1
|
||||||
%patch1009 -p1
|
%patch1009 -p1
|
||||||
%patch1010 -p1
|
%patch1010 -p1
|
||||||
|
%patch1011 -p1
|
||||||
|
|
||||||
%patch2000 -p1
|
%patch2000 -p1
|
||||||
%patch2002 -p1
|
%patch2002 -p1
|
||||||
%patch2003 -p1
|
%patch2003 -p1
|
||||||
%patch2005 -p1
|
%patch2005 -p1
|
||||||
%patch2006 -p1
|
%patch2006 -p1
|
||||||
%patch2007 -p1
|
|
||||||
|
|
||||||
%patch3000
|
%patch3000
|
||||||
|
|
||||||
|
@ -1,69 +1,37 @@
|
|||||||
[PR dynamic-link/18457]
|
2015-07-24 Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||||
* elf/dl-tls.c (tls_get_addr_tail): Don't take the rtld lock
|
|
||||||
if we already have a final static TLS offset.
|
|
||||||
* nptl/tst-join7.c, nptl/tst-join7mod.c: New.
|
|
||||||
|
|
||||||
Index: glibc-2.21/elf/dl-tls.c
|
[BZ #18457]
|
||||||
|
* nptl/Makefile (tests): New test case tst-join7.
|
||||||
|
(modules-names): New test case module tst-join7mod.
|
||||||
|
* nptl/tst-join7.c: New file.
|
||||||
|
* nptl/tst-join7mod.c: New file.
|
||||||
|
* Makeconfig (tls-model): Pass -ftls-model=initial-exec for
|
||||||
|
all translation units in libc.so, libpthread.so and rtld.
|
||||||
|
|
||||||
|
Index: glibc-2.21/Makeconfig
|
||||||
===================================================================
|
===================================================================
|
||||||
--- glibc-2.21.orig/elf/dl-tls.c
|
--- glibc-2.21.orig/Makeconfig
|
||||||
+++ glibc-2.21/elf/dl-tls.c
|
+++ glibc-2.21/Makeconfig
|
||||||
@@ -755,30 +755,44 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t
|
@@ -832,6 +832,10 @@ in-module = $(subst -,_,$(firstword $(li
|
||||||
the_map = listp->slotinfo[idx].map;
|
$(libof-$(@F)) \
|
||||||
}
|
libc))
|
||||||
|
|
||||||
- /* Make sure that, if a dlopen running in parallel forces the
|
+# Build ld.so, libc.so and libpthread.so with -ftls-model=initial-exec
|
||||||
- variable into static storage, we'll wait until the address in the
|
+tls-model = $(if $(filter libpthread rtld \
|
||||||
- static TLS block is set up, and use that. If we're undecided
|
+ libc,$(in-module)),-ftls-model=initial-exec,)
|
||||||
- yet, make sure we make the decision holding the lock as well. */
|
|
||||||
- if (__glibc_unlikely (the_map->l_tls_offset
|
|
||||||
- != FORCED_DYNAMIC_TLS_OFFSET))
|
|
||||||
+ /* If the TLS block for the map is already assigned to dynamic or to
|
|
||||||
+ static TLS, avoid the lock. Be careful to use the same value for
|
|
||||||
+ both tests; if we reloaded it, the second test might mistake
|
|
||||||
+ forced dynamic for an offset. Now, if the decision hasn't been
|
|
||||||
+ made, take the rtld lock, so that an ongoing dlopen gets a chance
|
|
||||||
+ to complete, and then retest; if the decision is still pending,
|
|
||||||
+ force the module to dynamic TLS. */
|
|
||||||
+ ptrdiff_t offset = atomic_load_relaxed (&the_map->l_tls_offset);
|
|
||||||
+ if (__glibc_unlikely (offset != FORCED_DYNAMIC_TLS_OFFSET))
|
|
||||||
{
|
|
||||||
+ if (__glibc_unlikely (offset != NO_TLS_OFFSET))
|
|
||||||
+ goto static_tls;
|
|
||||||
__rtld_lock_lock_recursive (GL(dl_load_lock));
|
|
||||||
- if (__glibc_likely (the_map->l_tls_offset == NO_TLS_OFFSET))
|
|
||||||
+ offset = the_map->l_tls_offset;
|
|
||||||
+ if (__glibc_likely (offset == NO_TLS_OFFSET))
|
|
||||||
{
|
|
||||||
the_map->l_tls_offset = FORCED_DYNAMIC_TLS_OFFSET;
|
|
||||||
__rtld_lock_unlock_recursive (GL(dl_load_lock));
|
|
||||||
}
|
|
||||||
- else if (__glibc_likely (the_map->l_tls_offset
|
|
||||||
- != FORCED_DYNAMIC_TLS_OFFSET))
|
|
||||||
+ else if (__glibc_likely (offset != FORCED_DYNAMIC_TLS_OFFSET))
|
|
||||||
{
|
|
||||||
+ /* The decision is made, and it is final. We use the value
|
|
||||||
+ we've already loaded, but we could even load the offset
|
|
||||||
+ after releasing the lock, since it won't change. Should
|
|
||||||
+ the module be released while another thread references
|
|
||||||
+ one of its TLS variables, that's undefined behavior. */
|
|
||||||
+ __rtld_lock_unlock_recursive (GL(dl_load_lock));
|
|
||||||
+
|
+
|
||||||
+ static_tls:
|
module-cppflags-real = -include $(common-objpfx)libc-modules.h \
|
||||||
+ ;
|
-DMODULE_NAME=$(in-module)
|
||||||
+
|
|
||||||
#if TLS_TCB_AT_TP
|
|
||||||
- void *p = (char *) THREAD_SELF - the_map->l_tls_offset;
|
|
||||||
+ void *p = (char *) THREAD_SELF - offset;
|
|
||||||
#elif TLS_DTV_AT_TP
|
|
||||||
- void *p = (char *) THREAD_SELF + the_map->l_tls_offset + TLS_PRE_TCB_SIZE;
|
|
||||||
+ void *p = (char *) THREAD_SELF + offset + TLS_PRE_TCB_SIZE;
|
|
||||||
#else
|
|
||||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
|
||||||
#endif
|
|
||||||
- __rtld_lock_unlock_recursive (GL(dl_load_lock));
|
|
||||||
|
|
||||||
dtv[GET_ADDR_MODULE].pointer.is_static = true;
|
@@ -855,7 +859,7 @@ CPPFLAGS = $(config-extra-cppflags) $(CP
|
||||||
dtv[GET_ADDR_MODULE].pointer.val = p;
|
override CFLAGS = -std=gnu99 $(gnu89-inline-CFLAGS) $(config-extra-cflags) \
|
||||||
|
$(filter-out %frame-pointer,$(+cflags)) $(+gccwarn-c) \
|
||||||
|
$(sysdep-CFLAGS) $(CFLAGS-$(suffix $@)) $(CFLAGS-$(<F)) \
|
||||||
|
- $(CFLAGS-$(@F)) \
|
||||||
|
+ $(CFLAGS-$(@F)) $(tls-model) \
|
||||||
|
$(foreach lib,$(libof-$(basename $(@F))) \
|
||||||
|
$(libof-$(<F)) $(libof-$(@F)),$(CFLAGS-$(lib)))
|
||||||
|
override CXXFLAGS = $(c++-sysincludes) \
|
||||||
Index: glibc-2.21/nptl/Makefile
|
Index: glibc-2.21/nptl/Makefile
|
||||||
===================================================================
|
===================================================================
|
||||||
--- glibc-2.21.orig/nptl/Makefile
|
--- glibc-2.21.orig/nptl/Makefile
|
||||||
@ -103,14 +71,48 @@ Index: glibc-2.21/nptl/tst-join7.c
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ glibc-2.21/nptl/tst-join7.c
|
+++ glibc-2.21/nptl/tst-join7.c
|
||||||
@@ -0,0 +1,12 @@
|
@@ -0,0 +1,46 @@
|
||||||
|
+/* Verify that TLS access in separate thread in a dlopened library does not
|
||||||
|
+ deadlock.
|
||||||
|
+ Copyright (C) 2015 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
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
+#include <dlfcn.h>
|
+#include <dlfcn.h>
|
||||||
+
|
+
|
||||||
|
+/* When one dynamically loads a module, which spawns a thread to perform some
|
||||||
|
+ activities, it could be possible that TLS storage is accessed for the first
|
||||||
|
+ time in that thread. This results in an allocation request within the
|
||||||
|
+ thread, which could result in an attempt to take the rtld load_lock. This
|
||||||
|
+ is a problem because it would then deadlock with the dlopen (which owns the
|
||||||
|
+ lock), if the main thread is waiting for the spawned thread to exit. We can
|
||||||
|
+ at least ensure that this problem does not occur due to accesses within
|
||||||
|
+ libc.so, by marking TLS variables within libc.so as IE. The problem of an
|
||||||
|
+ arbitrary variable being accessed and constructed within such a thread still
|
||||||
|
+ exists but this test case does not verify that. */
|
||||||
|
+
|
||||||
+int
|
+int
|
||||||
+do_test (void)
|
+do_test (void)
|
||||||
+{
|
+{
|
||||||
+ void *f = dlopen ("tst-join7mod.so", RTLD_NOW | RTLD_GLOBAL);
|
+ void *f = dlopen ("tst-join7mod.so", RTLD_NOW | RTLD_GLOBAL);
|
||||||
+ if (f) dlclose (f); else return 1;
|
+ if (f)
|
||||||
|
+ dlclose (f);
|
||||||
|
+ else
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
+ return 0;
|
+ return 0;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
@ -120,9 +122,30 @@ Index: glibc-2.21/nptl/tst-join7mod.c
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ glibc-2.21/nptl/tst-join7mod.c
|
+++ glibc-2.21/nptl/tst-join7mod.c
|
||||||
@@ -0,0 +1,29 @@
|
@@ -0,0 +1,62 @@
|
||||||
|
+/* Verify that TLS access in separate thread in a dlopened library does not
|
||||||
|
+ deadlock - the module.
|
||||||
|
+ Copyright (C) 2015 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
|
||||||
|
+ <http://www.gnu.org/licenses/>. */
|
||||||
|
+
|
||||||
+#include <stdio.h>
|
+#include <stdio.h>
|
||||||
|
+#include <string.h>
|
||||||
+#include <pthread.h>
|
+#include <pthread.h>
|
||||||
|
+#include <atomic.h>
|
||||||
+
|
+
|
||||||
+static pthread_t th;
|
+static pthread_t th;
|
||||||
+static int running = 1;
|
+static int running = 1;
|
||||||
@ -130,23 +153,35 @@ Index: glibc-2.21/nptl/tst-join7mod.c
|
|||||||
+static void *
|
+static void *
|
||||||
+test_run (void *p)
|
+test_run (void *p)
|
||||||
+{
|
+{
|
||||||
+ while (running)
|
+ while (atomic_load_relaxed (&running))
|
||||||
+ fprintf (stderr, "XXX test_run\n");
|
+ printf ("Test running\n");
|
||||||
+ fprintf (stderr, "XXX test_run FINISHED\n");
|
+ printf ("Test finished\n");
|
||||||
+ return NULL;
|
+ return NULL;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static void __attribute__ ((constructor))
|
+static void __attribute__ ((constructor))
|
||||||
+do_init (void)
|
+do_init (void)
|
||||||
+{
|
+{
|
||||||
+ pthread_create (&th, NULL, test_run, NULL);
|
+ int ret = pthread_create (&th, NULL, test_run, NULL);
|
||||||
|
+
|
||||||
|
+ if (ret != 0)
|
||||||
|
+ {
|
||||||
|
+ printf ("failed to create thread: %s (%d)\n", strerror (ret), ret);
|
||||||
|
+ exit (1);
|
||||||
|
+ }
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+static void __attribute__ ((destructor))
|
+static void __attribute__ ((destructor))
|
||||||
+do_end (void)
|
+do_end (void)
|
||||||
+{
|
+{
|
||||||
+ running = 0;
|
+ atomic_store_relaxed (&running, 0);
|
||||||
+ fprintf (stderr, "thread_join...\n");
|
+ int ret = pthread_join (th, NULL);
|
||||||
+ pthread_join (th, NULL);
|
+
|
||||||
+ fprintf (stderr, "thread_join DONE\n");
|
+ if (ret != 0)
|
||||||
|
+ {
|
||||||
|
+ printf ("pthread_join: %s(%d)\n", strerror (ret), ret);
|
||||||
|
+ exit (1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ printf ("Thread joined\n");
|
||||||
+}
|
+}
|
||||||
|
Loading…
Reference in New Issue
Block a user