GNU C Library master sources branch, master, updated. glibc-2.11-393-g5a2a1d7

drepper@sourceware.org drepper@sourceware.org
Mon May 3 15:09:00 GMT 2010


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  5a2a1d75043138e696222ced4560de2fb90b8024 (commit)
      from  c739ec3d81a34a87d8ae1276eab4f5880afc3476 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sources.redhat.com/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=5a2a1d75043138e696222ced4560de2fb90b8024

commit 5a2a1d75043138e696222ced4560de2fb90b8024
Author: Andreas Schwab <schwab@redhat.com>
Date:   Mon May 3 08:08:28 2010 -0700

    Don't deadlock in __dl_iterate_phdr while (un)loading objects.

diff --git a/ChangeLog b/ChangeLog
index ad1d327..4005fc8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2010-02-02  Andreas Schwab  <schwab@redhat.com>
+
+	* sysdeps/generic/ldsodefs.h (struct rtld_global): Add
+	_dl_load_write_lock.
+	* elf/rtld.c (_rtld_global): Initialize it.
+	* elf/dl-support.c (_dl_load_write_lock): Define .
+	* elf/dl-close.c (_dl_close_worker): Lock GL(dl_load_write_lock)
+	when modifying the list of loaded objects.
+	* elf/dl-load.c (lose): Likewise.
+	* elf/dl-object.c (_dl_new_object): Likewise.
+	* elf/dl-iteratephdr.c (__dl_iterate_phdr): Lock
+	GL(dl_load_write_lock) instead of GL(dl_load_lock).
+
 2010-05-03  Ulrich Drepper  <drepper@redhat.com>
 
 	* elf/dl-iteratephdr.c (__dl_iterate_phdr): Remove unnecessary
diff --git a/elf/dl-close.c b/elf/dl-close.c
index b73a7ad..700e765 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -507,6 +507,9 @@ _dl_close_worker (struct link_map *map)
   size_t tls_free_end;
   tls_free_start = tls_free_end = NO_TLS_OFFSET;
 
+  /* We modify the list of loaded objects.  */
+  __rtld_lock_lock_recursive (GL(dl_load_write_lock));
+
   /* Check each element of the search list to see if all references to
      it are gone.  */
   for (unsigned int i = first_loaded; i < nloaded; ++i)
@@ -665,6 +668,8 @@ _dl_close_worker (struct link_map *map)
 	}
     }
 
+  __rtld_lock_unlock_recursive (GL(dl_load_write_lock));
+
   /* If we removed any object which uses TLS bump the generation counter.  */
   if (any_tls)
     {
diff --git a/elf/dl-iteratephdr.c b/elf/dl-iteratephdr.c
index 44864c1..5f1c20d 100644
--- a/elf/dl-iteratephdr.c
+++ b/elf/dl-iteratephdr.c
@@ -26,7 +26,7 @@
 static void
 cancel_handler (void *arg __attribute__((unused)))
 {
-  __rtld_lock_unlock_recursive (GL(dl_load_lock));
+  __rtld_lock_unlock_recursive (GL(dl_load_write_lock));
 }
 
 hidden_proto (__dl_iterate_phdr)
@@ -38,8 +38,8 @@ __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
   struct dl_phdr_info info;
   int ret = 0;
 
-  /* Make sure we are alone.  */
-  __rtld_lock_lock_recursive (GL(dl_load_lock));
+  /* Make sure nobody modifies the list of loaded objects.  */
+  __rtld_lock_lock_recursive (GL(dl_load_write_lock));
   __libc_cleanup_push (cancel_handler, 0);
 
   /* We have to determine the namespace of the caller since this determines
@@ -79,7 +79,7 @@ __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
 
   /* Release the lock.  */
   __libc_cleanup_pop (0);
-  __rtld_lock_unlock_recursive (GL(dl_load_lock));
+  __rtld_lock_unlock_recursive (GL(dl_load_write_lock));
 
   return ret;
 }
diff --git a/elf/dl-load.c b/elf/dl-load.c
index d8f9131..0adddf5 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -803,6 +803,8 @@ lose (int code, int fd, const char *name, char *realname, struct link_map *l,
     (void) __close (fd);
   if (l != NULL)
     {
+      /* We modify the list of loaded objects.  */
+      __rtld_lock_lock_recursive (GL(dl_load_write_lock));
       /* Remove the stillborn object from the list and free it.  */
       assert (l->l_next == NULL);
       if (l->l_prev == NULL)
@@ -813,6 +815,7 @@ lose (int code, int fd, const char *name, char *realname, struct link_map *l,
 	l->l_prev->l_next = NULL;
       --GL(dl_ns)[l->l_ns]._ns_nloaded;
       free (l);
+      __rtld_lock_unlock_recursive (GL(dl_load_write_lock));
     }
   free (realname);
 
diff --git a/elf/dl-object.c b/elf/dl-object.c
index 788e2c0..22a1635 100644
--- a/elf/dl-object.c
+++ b/elf/dl-object.c
@@ -93,6 +93,9 @@ _dl_new_object (char *realname, const char *libname, int type,
   new->l_scope = new->l_scope_mem;
   new->l_scope_max = sizeof (new->l_scope_mem) / sizeof (new->l_scope_mem[0]);
 
+  /* We modify the list of loaded objects.  */
+  __rtld_lock_lock_recursive (GL(dl_load_write_lock));
+
   /* Counter for the scopes we have to handle.  */
   idx = 0;
 
@@ -114,6 +117,8 @@ _dl_new_object (char *realname, const char *libname, int type,
   new->l_serial = GL(dl_load_adds);
   ++GL(dl_load_adds);
 
+  __rtld_lock_unlock_recursive (GL(dl_load_write_lock));
+
   /* If we have no loader the new object acts as it.  */
   if (loader == NULL)
     loader = new;
diff --git a/elf/dl-support.c b/elf/dl-support.c
index 65b2575..f94d2c4 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -166,6 +166,10 @@ const ElfW(Ehdr) *_dl_sysinfo_dso;
    the loaded object might as well require a call to this function.
    At this time it is not anymore a problem to modify the tables.  */
 __rtld_lock_define_initialized_recursive (, _dl_load_lock)
+/* This lock is used to keep __dl_iterate_phdr from inspecting the
+   list of loaded objects while an object is added to or removed from
+   that list.  */
+__rtld_lock_define_initialized_recursive (, _dl_load_write_lock)
 
 
 #ifdef HAVE_AUX_VECTOR
diff --git a/elf/rtld.c b/elf/rtld.c
index e26b2b9..90f3ff1 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -126,6 +126,7 @@ struct rtld_global _rtld_global =
     ._dl_stack_flags = PF_R|PF_W|PF_X,
 #ifdef _LIBC_REENTRANT
     ._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
+    ._dl_load_write_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
 #endif
     ._dl_nns = 1,
     ._dl_ns =
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index a14e8af..fcc943b 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -416,6 +416,10 @@ struct rtld_global
      the loaded object might as well require a call to this function.
      At this time it is not anymore a problem to modify the tables.  */
   __rtld_lock_define_recursive (EXTERN, _dl_load_lock)
+  /* This lock is used to keep __dl_iterate_phdr from inspecting the
+     list of loaded objects while an object is added to or removed
+     from that list.  */
+  __rtld_lock_define_recursive (EXTERN, _dl_load_write_lock)
 
   /* Incremented whenever something may have been added to dl_loaded.  */
   EXTERN unsigned long long _dl_load_adds;

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                  |   13 +++++++++++++
 elf/dl-close.c             |    5 +++++
 elf/dl-iteratephdr.c       |    8 ++++----
 elf/dl-load.c              |    3 +++
 elf/dl-object.c            |    5 +++++
 elf/dl-support.c           |    4 ++++
 elf/rtld.c                 |    1 +
 sysdeps/generic/ldsodefs.h |    4 ++++
 8 files changed, 39 insertions(+), 4 deletions(-)


hooks/post-receive
-- 
GNU C Library master sources



More information about the Glibc-cvs mailing list