public inbox for
 help / color / mirror / Atom feed
From: Jakub Jelinek <>
To: Ulrich Drepper <>
Cc: Glibc hackers <>
Subject: [PATCH] Fix __libc_rwlock_* in NPTL
Date: Wed, 10 Oct 2007 12:32:00 -0000	[thread overview]
Message-ID: <> (raw)


#include <dlfcn.h>
#include <libintl.h>
#include <locale.h>
#include <malloc.h>

main (void)
  mallopt (M_PERTURB, 152);
  dlopen ("", RTLD_LAZY);
  setlocale (LC_ALL, "ja_JP.UTF-8");
  textdomain ("libc");
  dgettext (NULL, "Hangup");
  return 0;

hangs with trunk glibc when linked with -ldl, but not -lpthread.
The problem is that while __libc_rwlock_{rd,wr,un}lock use
__libc_ptf_call macro and therefore in will call
some __libc_pthread_functions.* function, __libc_rwlock_{init,fini}
use __libc_maybe_call, which
1) means additional relocations in (two for each even)
2) if is lt_loaded, then the weak relocs in
   are resolved to NULL and therefore __libc_rwlock_{init,fini}
   is essentially a nop.  So conversions_lock (the only one
   for which we use __libc_rwlock_init ATM) is unitialized, but
   later we call __libc_rwlock_rdlock etc. on it - if
   is loaded at that point, it is accessing unitialized data
One possible fix might seem to be making __libc_rwlock_init
also __libc_ptf_call (i.e. add another function pointer to
__libc_pthread_functions).  But that is IMHO still risky,
we don't have any hook which would be called when
is called.  If a program not linked against
calls dgettext which needs conversions (__libc_rwlock_init
would do nothing, as __libc_pthread_functions wasn't inited,
__libc_rwlock_rdlock etc. would be a nop too for the same reasons),
then dlopens and then calls dgettext for the same domain
(which is still around, hasn't been unloaded), then nothing calls
__libc_rwlock_init again, but __libc_rwlock_rdlock is used on unitialized

IMHO we don't need to call any function for this inside of,
we know the pthread library is NPTL and how are its rwlocks initialized.
Unfortunately, GCC, even including GCC 4.3, generates terrible code
for ((NAME) = (pthread_rwlock_t) PTHREAD_RWLOCK_INITIALIZER, 0)
- filed upstream PR about it - but ATM we know it is all zeros.
I have added a test for that with a comment to tst-initializers1.c,
so that if we ever change it, we'll be reminded to change

2007-10-10  Jakub Jelinek  <>

	* sysdeps/pthread/bits/libc-lock.h (__libc_rwlock_init): Inside of just clear NAME.
	(__libc_rwlock_fini): Nop inside of
	* tst-initializers1.c (main): Test if PTHREAD_RWLOCK_INITIALIZER is
	all zeros.

--- libc/nptl/sysdeps/pthread/bits/libc-lock.h.jj	2007-10-10 12:50:11.000000000 +0200
+++ libc/nptl/sysdeps/pthread/bits/libc-lock.h	2007-10-10 13:21:42.000000000 +0200
@@ -172,8 +172,15 @@ typedef pthread_key_t __libc_key_t;
 # define __libc_lock_init(NAME) \
   __libc_maybe_call (__pthread_mutex_init, (&(NAME), NULL), 0)
-#define __libc_rwlock_init(NAME) \
+#if defined SHARED && !defined NOT_IN_libc
+/* ((NAME) = (__libc_rwlock_t) PTHREAD_RWLOCK_INITIALIZER, 0) is
+   inefficient.  */
+# define __libc_rwlock_init(NAME) \
+  (__builtin_memset (&(NAME), '\0', sizeof (NAME)), 0)
+# define __libc_rwlock_init(NAME) \
   __libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0)
 /* Same as last but this time we initialize a recursive mutex.  */
 #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)
@@ -214,8 +221,12 @@ typedef pthread_key_t __libc_key_t;
 # define __libc_lock_fini(NAME) \
   __libc_maybe_call (__pthread_mutex_destroy, (&(NAME)), 0)
-#define __libc_rwlock_fini(NAME) \
+#if defined SHARED && !defined NOT_IN_libc
+# define __libc_rwlock_fini(NAME) ((void) 0)
+# define __libc_rwlock_fini(NAME) \
   __libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0)
 /* Finalize recursive named lock.  */
 #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)
--- libc/nptl/tst-initializers1.c.jj	2007-06-04 08:42:05.000000000 +0200
+++ libc/nptl/tst-initializers1.c	2007-10-10 13:26:04.000000000 +0200
@@ -47,5 +47,12 @@ main (void)
   if (rwl_writer.__data.__flags
     return 6;
+  /* <bits/libc-lock.h> __libc_rwlock_init definition for
+     relies on PTHREAD_RWLOCK_INITIALIZER being all zeros.  If
+     that ever changes, <bits/libc-lock.h> needs updating.  */
+  size_t i;
+  for (i = 0; i < sizeof (rwl_normal); i++)
+    if (((char *) &rwl_normal)[i] != '\0')
+      return 7;
   return 0;


                 reply	other threads:[~2007-10-10 12:32 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \ \ \ \ \

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).