about summary refs log tree commit diff
path: root/elf/dl-close.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/dl-close.c')
-rw-r--r--elf/dl-close.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 7e851cd0af..fa9e92cb9f 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -1,5 +1,5 @@
-/* _dl_close -- Close a shared object opened by `_dl_open'.
-   Copyright (C) 1996 Free Software Foundation, Inc.
+/* Close a shared object opened by `_dl_open'.
+   Copyright (C) 1996, 1997 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
@@ -23,8 +23,14 @@
 #include <string.h>
 #include <sys/types.h>
 #include <sys/mman.h>
+#include <libc-lock.h>
 
 
+/* During the program run we must not modify the global data of
+   loaded shared object simultanously in two threads.  Therefore we
+   protect `dlopen' and `dlclose' in dlclose.c.  */
+__libc_lock_define (extern, _dl_load_lock)
+
 #define LOSE(s) _dl_signal_error (0, map->l_name, s)
 
 void
@@ -36,10 +42,16 @@ _dl_close (struct link_map *map)
   if (map->l_opencount == 0)
     LOSE ("shared object not open");
 
+  /* Acquire the lock.  */
+  __libc_lock_lock (_dl_load_lock);
+
   /* 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;
+    {
+      /* There are still references to this object.  Do nothing more.  */
+      __libc_lock_unlock (_dl_load_lock);
+      return;
+    }
 
   /* Notify the debugger we are about to remove some loaded objects.  */
   _r_debug.r_state = RT_DELETE;
@@ -114,4 +126,7 @@ _dl_close (struct link_map *map)
   /* Notify the debugger those objects are finalized and gone.  */
   _r_debug.r_state = RT_CONSISTENT;
   _dl_debug_state ();
+
+  /* Release the lock.  */
+  __libc_lock_unlock (_dl_load_lock);
 }