Individual debuginfod_client objects and their underlying CURLM handles
should not be used concurrently during calls to
__libdwfl_debuginfod_find_debuginfo and
__libdwfl_debuginfod_find_executable.

Add a mutex field to struct Dwfl and synchronize calls to
__libdwfl_debuginfod_find_*.

Signed-off-by: Aaron Merey <[email protected]>
---
 libdwfl/debuginfod-client.c | 9 +++++++--
 libdwfl/dwfl_begin.c        | 2 ++
 libdwfl/dwfl_end.c          | 1 +
 libdwfl/libdwflP.h          | 1 +
 4 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/libdwfl/debuginfod-client.c b/libdwfl/debuginfod-client.c
index 882a5eff..4b457da4 100644
--- a/libdwfl/debuginfod-client.c
+++ b/libdwfl/debuginfod-client.c
@@ -49,7 +49,7 @@ static void __libdwfl_debuginfod_init (void);
 
 static pthread_once_t init_control = PTHREAD_ONCE_INIT;
 
-/* NB: this is slightly thread-unsafe */
+/* A per-Dwfl lock must be held when calling this function.  */
 
 debuginfod_client *
 dwfl_get_debuginfod_client (Dwfl *dwfl)
@@ -77,10 +77,12 @@ __libdwfl_debuginfod_find_executable (Dwfl *dwfl,
   int fd = -1;
   if (build_id_len > 0)
     {
+      mutex_lock (dwfl->lock);
       debuginfod_client *c = INTUSE (dwfl_get_debuginfod_client) (dwfl);
       if (c != NULL)
        fd = (*fp_debuginfod_find_executable) (c, build_id_bits,
                                               build_id_len, NULL);
+      mutex_unlock (dwfl->lock);
     }
 
   return fd;
@@ -94,10 +96,12 @@ __libdwfl_debuginfod_find_debuginfo (Dwfl *dwfl,
   int fd = -1;
   if (build_id_len > 0)
     {
+      mutex_lock (dwfl->lock);
       debuginfod_client *c = INTUSE (dwfl_get_debuginfod_client) (dwfl);
       if (c != NULL)
        fd = (*fp_debuginfod_find_debuginfo) (c, build_id_bits,
                                              build_id_len, NULL);
+      mutex_unlock (dwfl->lock);
     }
 
   return fd;
@@ -111,7 +115,8 @@ __libdwfl_debuginfod_end (debuginfod_client *c)
 }
 
 /* Try to get the libdebuginfod library functions.
-   Only needs to be called once from dwfl_get_debuginfod_client.  */
+   Only needs to be called once from dwfl_get_debuginfod_client.
+   A per-Dwfl lock must be held when calling this function.  */
 static void
 __libdwfl_debuginfod_init (void)
 {
diff --git a/libdwfl/dwfl_begin.c b/libdwfl/dwfl_begin.c
index b03f5cf4..71947851 100644
--- a/libdwfl/dwfl_begin.c
+++ b/libdwfl/dwfl_begin.c
@@ -50,6 +50,8 @@ dwfl_begin (const Dwfl_Callbacks *callbacks)
       dwfl->offline_next_address = OFFLINE_REDZONE;
     }
 
+  mutex_init (dwfl->lock);
+
   return dwfl;
 }
 INTDEF (dwfl_begin)
diff --git a/libdwfl/dwfl_end.c b/libdwfl/dwfl_end.c
index d9cf569b..594051f0 100644
--- a/libdwfl/dwfl_end.c
+++ b/libdwfl/dwfl_end.c
@@ -53,6 +53,7 @@ dwfl_end (Dwfl *dwfl)
   free (dwfl->lookup_module);
   free (dwfl->lookup_segndx);
   free (dwfl->sysroot);
+  mutex_fini (dwfl->lock);
 
   Dwfl_Module *next = dwfl->modulelist;
   while (next != NULL)
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
index a5d88d60..341c0527 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -141,6 +141,7 @@ struct Dwfl
   struct Dwfl_User_Core *user_core;
   char *sysroot;               /* sysroot, or NULL to search standard system
                                   paths */
+  mutex_define (, lock);       /* Synchronize concurrent access.  */
 };
 
 #define OFFLINE_REDZONE                0x10000
-- 
2.51.1

Reply via email to