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 to serialize calls to
__libdwfl_debuginfod_find_*.

Signed-off-by: Aaron Merey <[email protected]>
---

v3 changes: In libdwfl.h, add the following to the comment for
dwfl_get_debuginfod_client:

The returned debuginfod-client handle must not be used at the same time as
any libdwfl function taking the client's associated DWFL as an argument.

 libdwfl/debuginfod-client.c | 6 +++++-
 libdwfl/dwfl_begin.c        | 2 ++
 libdwfl/dwfl_end.c          | 1 +
 libdwfl/libdwfl.h           | 3 +++
 libdwfl/libdwflP.h          | 3 +++
 5 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/libdwfl/debuginfod-client.c b/libdwfl/debuginfod-client.c
index 882a5eff..ecb053fc 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 */
+/* dwfl->debuginfod_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->debuginfod_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->debuginfod_lock);
     }
 
   return fd;
@@ -94,10 +96,12 @@ __libdwfl_debuginfod_find_debuginfo (Dwfl *dwfl,
   int fd = -1;
   if (build_id_len > 0)
     {
+      mutex_lock (dwfl->debuginfod_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->debuginfod_lock);
     }
 
   return fd;
diff --git a/libdwfl/dwfl_begin.c b/libdwfl/dwfl_begin.c
index b03f5cf4..835de8e3 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->debuginfod_lock);
+
   return dwfl;
 }
 INTDEF (dwfl_begin)
diff --git a/libdwfl/dwfl_end.c b/libdwfl/dwfl_end.c
index d9cf569b..c82d83fb 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->debuginfod_lock);
 
   Dwfl_Module *next = dwfl->modulelist;
   while (next != NULL)
diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h
index 90523283..e94dacdf 100644
--- a/libdwfl/libdwfl.h
+++ b/libdwfl/libdwfl.h
@@ -835,6 +835,9 @@ int dwfl_frame_reg (Dwfl_Frame *state, unsigned regno, 
Dwarf_Word *val)
    When the client connection has not yet been initialized, it will be done on 
the
    first call to this function. If elfutils is compiled without support for 
debuginfod,
    NULL will be returned.
+
+   The returned debuginfod-client handle must not be used at the same time as
+   any libdwfl function taking the client's associated DWFL as an argument.
  */
 extern debuginfod_client *dwfl_get_debuginfod_client (Dwfl *dwfl);
 
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
index a5d88d60..6e394c26 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -141,6 +141,9 @@ struct Dwfl
   struct Dwfl_User_Core *user_core;
   char *sysroot;               /* sysroot, or NULL to search standard system
                                   paths */
+
+  /* Serialize debuginfod_client usage.  */
+  mutex_define (, debuginfod_lock);
 };
 
 #define OFFLINE_REDZONE                0x10000
-- 
2.52.0

Reply via email to