]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Call shared object terminators at the right time.
authorUlrich Drepper <drepper@redhat.com>
Wed, 20 May 1998 12:09:18 +0000 (12:09 +0000)
committerUlrich Drepper <drepper@redhat.com>
Wed, 20 May 1998 12:09:18 +0000 (12:09 +0000)
elf/dl-close.c

index e49054acee4f19d3ea708e8b4f9ef04b590b9432..9cfc4ee1fec4b67d53ee30ef0a92111109b4bbce 100644 (file)
@@ -37,27 +37,38 @@ _dl_close (struct link_map *map)
     LOSE ("shared object not open");
 
   /* Decrement the reference count.  */
-  if (--map->l_opencount > 0 || map->l_type != lt_loaded)
-    /* There are still references to this object.  Do nothing more.  */
-    return;
+  if (map->l_opencount > 1 || map->l_type != lt_loaded)
+    {
+      /* There are still references to this object.  Do nothing more.  */
+      --map->l_opencount;
+      return;
+    }
+
+  list = map->l_searchlist;
+
+  /* Call all termination functions at once.  */
+  for (i = 0; i < map->l_nsearchlist; ++i)
+    {
+      struct link_map *imap = list[i];
+      if (imap->l_opencount == 1 && imap->l_type == lt_loaded)
+       {
+         if (imap->l_info[DT_FINI])
+           /* Call its termination function.  */
+           (*(void (*) (void)) ((void *) imap->l_addr
+                                + imap->l_info[DT_FINI]->d_un.d_ptr)) ();
+       }
+    }
 
   /* Notify the debugger we are about to remove some loaded objects.  */
   _r_debug.r_state = RT_DELETE;
   _dl_debug_state ();
 
-  list = map->l_searchlist;
-
   /* The search list contains a counted reference to each object it
      points to, the 0th elt being MAP itself.  Decrement the reference
      counts on all the objects MAP depends on.  */
-  for (i = 1; i < map->l_nsearchlist; ++i)
+  for (i = 0; i < map->l_nsearchlist; ++i)
     --list[i]->l_opencount;
 
-  /* Clear the search list so it doesn't get freed while we are still
-     using it.  We have cached it in LIST and will free it when
-     finished.  */
-  map->l_searchlist = NULL;
-
   /* Check each element of the search list to see if all references to
      it are gone.  */
   for (i = 0; i < map->l_nsearchlist; ++i)
@@ -71,11 +82,6 @@ _dl_close (struct link_map *map)
          const ElfW(Phdr) *first, *last;
          ElfW(Addr) mapstart, mapend;
 
-         if (imap->l_info[DT_FINI])
-           /* Call its termination function.  */
-           (*(void (*) (void)) ((void *) imap->l_addr
-                                + imap->l_info[DT_FINI]->d_un.d_ptr)) ();
-
          if (imap->l_global)
            {
              /* This object is in the global scope list.  Remove it.  */
@@ -110,7 +116,7 @@ _dl_close (struct link_map *map)
            imap->l_prev->l_next = imap->l_next;
          if (imap->l_next)
            imap->l_next->l_prev = imap->l_prev;
-         if (imap->l_searchlist)
+         if (imap->l_searchlist && imap->l_searchlist != list)
            free (imap->l_searchlist);
          free (imap);
        }