Hi Aaron,

On Fri, 2025-12-19 at 17:39 -0500, Aaron Merey wrote:
> 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.

Yes, that is a good comment. So basically you have to use the handle
before you start using the Dwfl itself.

Locking itself looks correct.
 
> -/* NB: this is slightly thread-unsafe */
> +/* dwfl->debuginfod_lock must be held when calling this function.  */
>  
>  debuginfod_client *
>  dwfl_get_debuginfod_client (Dwfl *dwfl)

OK. When calling the function and calling a method on the handle.

> @@ -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;

Good.

> @@ -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;

Same.

> 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)

OK, begin inits the lock.

> 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)

And end finis it.

> 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);

Ack, as above.

>  
> 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);
>  };

OK, new lock field in Dwfl struct.

Thanks,

Mark

Reply via email to