]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
libdw: make dwarf_getalt thread-safe
authorHeather McIntyre <hsm2@rice.edu>
Tue, 10 Oct 2023 13:42:54 +0000 (15:42 +0200)
committerAaron Merey <amerey@redhat.com>
Tue, 4 Jun 2024 19:08:56 +0000 (15:08 -0400)
* libdw/dwarf_getalt.c: Add lock for
dbg->alt_dwarf/main->alt_dwarf.

Signed-off-by: Heather S. McIntyre <hsm2@rice.edu>
Signed-off-by: Mark Wielaard <mark@klomp.org>
libdw/dwarf_getalt.c

index 0a12dfae96772bf49033da744d5db9255aaf3440..e3894c8c509d861bc9ce6f6a999631152197aee9 100644 (file)
 #include <sys/types.h>
 #include <sys/stat.h>
 
+/* find_debug_altlink() modifies "dbg->alt_dwarf".
+   dwarf_getalt() reads "main->alt_dwarf".
+   Mutual exclusion is enforced to prevent a race. */
+rwlock_define(static, alt_dwarf_lock);
 
 char *
 internal_function
@@ -152,7 +156,9 @@ find_debug_altlink (Dwarf *dbg)
       Dwarf *alt = dwarf_begin (fd, O_RDONLY);
       if (alt != NULL)
        {
+         rwlock_wrlock(alt_dwarf_lock);
          dbg->alt_dwarf = alt;
+         rwlock_unlock(alt_dwarf_lock);
          dbg->alt_fd = fd;
        }
       else
@@ -163,22 +169,33 @@ find_debug_altlink (Dwarf *dbg)
 Dwarf *
 dwarf_getalt (Dwarf *main)
 {
+  rwlock_rdlock(alt_dwarf_lock);
+  Dwarf *alt_dwarf_local = main->alt_dwarf;
+  rwlock_unlock(alt_dwarf_lock);
+
   /* Only try once.  */
-  if (main == NULL || main->alt_dwarf == (void *) -1)
+  if (main == NULL || alt_dwarf_local == (void *) -1)
     return NULL;
 
-  if (main->alt_dwarf != NULL)
-    return main->alt_dwarf;
+  if (alt_dwarf_local != NULL)
+    return alt_dwarf_local;
 
   find_debug_altlink (main);
 
+  rwlock_rdlock(alt_dwarf_lock);
+  alt_dwarf_local = main->alt_dwarf;
+  rwlock_unlock(alt_dwarf_lock);
+
   /* If we found nothing, make sure we don't try again.  */
-  if (main->alt_dwarf == NULL)
+  if (alt_dwarf_local == NULL)
     {
+      rwlock_wrlock(alt_dwarf_lock);
       main->alt_dwarf = (void *) -1;
+      rwlock_unlock(alt_dwarf_lock);
+
       return NULL;
     }
 
-  return main->alt_dwarf;
+  return alt_dwarf_local;
 }
 INTDEF (dwarf_getalt)