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
