Sourceware Bugzilla – Attachment 8326 Details for
Bug 18435
pthread_once hangs when init routine throws an exception
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Proposed patch tested on powerpc64le and x86_64.
glibc-18435-pthread_once.patch (text/plain), 6.28 KB, created by
Martin Sebor
on 2015-05-20 00:09:43 UTC
(
hide
)
Description:
Proposed patch tested on powerpc64le and x86_64.
Filename:
MIME Type:
Creator:
Martin Sebor
Created:
2015-05-20 00:09:43 UTC
Size:
6.28 KB
patch
obsolete
>diff --git a/ChangeLog b/ChangeLog >index b7f3c61..943ce60 100644 >--- a/ChangeLog >+++ b/ChangeLog >@@ -1,3 +1,13 @@ >+2015-05-19 Martin Sebor <msebor@redhat.com> >+ >+ [BZ #18???] >+ * nptl/ptherad_once (CleanupInfo): New struct. >+ (clear_once_control): Replace... >+ (cleanup_maybe_clear_once_control): ...with this. >+ (__pthread_once_slow): Replace calls to pthread_cleanup_push and >+ pthread_cleanup_pop with a cleanup object of struct CleanupInfo. >+ * nptl/tst-once5.cc: New test. >+ > 2015-05-18 Siddhesh Poyarekar <siddhesh@redhat.com> > > * .gitignore: Ignore generated *.pyc. >diff --git a/nptl/Makefile b/nptl/Makefile >index d784c8d..1bf35cb 100644 >--- a/nptl/Makefile >+++ b/nptl/Makefile >@@ -203,6 +203,7 @@ CFLAGS-send.c = -fexceptions -fasynchronous-unwind-tables > > CFLAGS-pt-system.c = -fexceptions > >+LDFLAGS-tst-once5 = -lstdc++ > > tests = tst-typesizes \ > tst-attr1 tst-attr2 tst-attr3 tst-default-attr \ >@@ -224,7 +225,7 @@ tests = tst-typesizes \ > tst-rwlock1 tst-rwlock2 tst-rwlock2a tst-rwlock3 tst-rwlock4 \ > tst-rwlock5 tst-rwlock6 tst-rwlock7 tst-rwlock8 tst-rwlock9 \ > tst-rwlock10 tst-rwlock11 tst-rwlock12 tst-rwlock13 tst-rwlock14 \ >- tst-once1 tst-once2 tst-once3 tst-once4 \ >+ tst-once1 tst-once2 tst-once3 tst-once4 tst-once5 \ > tst-key1 tst-key2 tst-key3 tst-key4 \ > tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \ > tst-sem8 tst-sem9 tst-sem10 tst-sem11 tst-sem12 tst-sem13 tst-sem14 \ >diff --git a/nptl/pthread_once.c b/nptl/pthread_once.c >index fe6d923..8905b8f 100644 >--- a/nptl/pthread_once.c >+++ b/nptl/pthread_once.c >@@ -23,19 +23,24 @@ > > unsigned long int __fork_generation attribute_hidden; > >+struct CleanupInfo { >+ pthread_once_t *once; >+}; > > static void >-clear_once_control (void *arg) >+cleanup_maybe_clear_once_control (struct CleanupInfo *pinfo) > { >- pthread_once_t *once_control = (pthread_once_t *) arg; >- >- /* Reset to the uninitialized state here. We don't need a stronger memory >- order because we do not need to make any other of our writes visible to >- other threads that see this value: This function will be called if we >- get interrupted (see __pthread_once), so all we need to relay to other >- threads is the state being reset again. */ >- atomic_store_relaxed (once_control, 0); >- lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); >+ if (pinfo->once) { >+ >+ /* Reset the once control variable to the uninitialized state here. >+ We don't need a stronger memory order because we do not need to >+ make any other of our writes visible to other threads that see >+ this value: This function will be called if we get interrupted >+ (see __pthread_once), so all we need to relay to other threads >+ is the state being reset again. */ >+ atomic_store_relaxed (pinfo->once, 0); >+ lll_futex_wake (pinfo->once, INT_MAX, LLL_PRIVATE); >+ } > } > > >@@ -107,14 +112,18 @@ __pthread_once_slow (pthread_once_t *once_control, void (*init_routine) (void)) > } > > /* This thread is the first here. Do the initialization. >- Register a cleanup handler so that in case the thread gets >- interrupted the initialization can be restarted. */ >- pthread_cleanup_push (clear_once_control, once_control); >+ Register a cleanup handler so that in case the thread gets >+ interrupted or the initialization routine exits by throwing >+ an exception the initialization can be restarted. */ > >- init_routine (); >+ struct CleanupInfo >+ cleanupobj __attribute__ ((cleanup (cleanup_maybe_clear_once_control))) >+ = { .once = once_control }; > >- pthread_cleanup_pop (0); >+ init_routine (); > >+ /* Reset the once control variable to disable cleanup. */ >+ cleanupobj.once = 0; > > /* Mark *once_control as having finished the initialization. We need > release memory order here because we need to synchronize with other >diff --git a/nptl/tst-once5.cc b/nptl/tst-once5.cc >new file mode 100644 >index 0000000..60bc78a >--- /dev/null >+++ b/nptl/tst-once5.cc >@@ -0,0 +1,80 @@ >+/* Copyright (C) 2015 Free Software Foundation, Inc. >+ This file is part of the GNU C Library. >+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. >+ >+ 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 <errno.h> >+#include <pthread.h> >+#include <stdio.h> >+#include <string.h> >+ >+ >+static pthread_once_t once = PTHREAD_ONCE_INIT; >+ >+// Exception type thrown from the pthread_once init routine. >+struct OnceException { }; >+ >+// Test iteration counter. >+static int niter; >+ >+static void >+init_routine (void) >+{ >+ if (niter < 2) >+ throw OnceException (); >+} >+ >+// Verify that an exception thrown from the pthread_once init routine >+// is propagated to the pthread_once caller and that the function can >+// be subsequently invoked to attempt the initialization again. >+static int >+do_test (void) >+{ >+ int result = 1; >+ >+ // Repeat three times, having the init routine throw the first two >+ // times and succeed on the final attempt. >+ for (niter = 0; niter != 3; ++niter) { >+ >+ try { >+ int rc = pthread_once (&once, init_routine); >+ if (rc) >+ fprintf (stderr, "pthread_once failed: %i (%s)\n", >+ rc, strerror (rc)); >+ >+ if (niter < 2) >+ fputs ("pthread_once unexpectedly returned without" >+ " throwing an exception", stderr); >+ } >+ catch (OnceException) { >+ if (1 < niter) >+ fputs ("pthread_once unexpectedly threw", stderr); >+ result = 0; >+ } >+ catch (...) { >+ fputs ("pthread_once threw an unknown exception", stderr); >+ } >+ >+ // Abort the test on the first failure. >+ if (result) >+ break; >+ } >+ >+ return result; >+} >+ >+#define TEST_FUNCTION do_test () >+#include "../test-skeleton.c"
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 18435
: 8326 |
8329
|
10780