[PATCH 1/2] Thread-safety improvements for bfd_check_format_matches

Alan Modra amodra@gmail.com
Wed Apr 10 03:39:08 GMT 2024


On Sun, Mar 24, 2024 at 03:08:05PM -0600, Tom Tromey wrote:
> A gdb bug found that bfd_check_format_matches has some data races when
> called from multiple threads.
> 
> In particular, it changes the BFD error handler, which is a global.
> It also has a local static variable ("in_check_format") that is used
> for recursion detection.  And, finally, it may emit warnings to the
> per-xvec warning array, which is a global.
> 
> This patch removes all the races here.  I believe it does not change
> the current semantics, but I was unable to get the test file that
> would let me test that.

I suspect you have changed things a little.  The curent per_xvec_warn
array has an extra element to cache messages emitted when xvec is
NULL.  I added that just in case such a thing ever happened.  I don't
think it does, so I'm not at all concerned about a change in behaviour
when xvec is NULL.

However, the new _bfd_per_xvec_warn does seem to be a little weird
should messages->abfd-xvec ever be NULL.  It seems it will create a
new entry in the list for a NULL targ that then might be reused for a
later non-NULL targ message.  Also, the description for the new
_bfd_per_xvec_warn needs updating and maybe the function should be
made static and moved from targets.c to bfd.c.

> The first part of patch is to change _bfd_error_handler to directly
> handle the needs of bfd_check_format_matches.  This way, the error
> handler does not need to be changed.
> 
> This change lets us use the new per-thread global
> (error_handler_messages, replacing error_handler_bfd) to also remove
> the need for in_check_format -- a single variable suffices.
> 
> Finally, the global per-xvec array is replaced with a new type that
> holds the error messages.  The outermost such type is stack-allocated
> in bfd_check_format_matches.
> 
> I tested this using the binutils test suite.  I also built gdb with
> thread sanitizer and ran the test case that was noted as failing.
> 
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31264
> ---
>  bfd/bfd.c     | 68 ++++++++++++++++++++++++++++++++++++++-----------
>  bfd/format.c  | 70 +++++++++++++++++++++++----------------------------
>  bfd/libbfd.h  | 17 +++++++++++--
>  bfd/targets.c | 59 ++++++++++++++++++++++++++++++-------------
>  4 files changed, 142 insertions(+), 72 deletions(-)
> 

>  SYNOPSIS
> -	bfd_error_handler_type _bfd_set_error_handler_caching (bfd *);
> +	struct per_xvec_messages *_bfd_set_error_handler_caching (struct per_xvec_messages *);
>  
>  DESCRIPTION
>  	Set the BFD error handler function to one that stores messages
> -	to the per_xvec_warn array.  Returns the previous function.
> +	to the per_xvec_warn array.  Returns the previous BFD to which
> +	messages are stored.  Note that two sequential calls to this
> +	with a non-NULL BFD will cause output to be dropped, rather
> +	than gathered.
>  */

non-NULL BFD?

-- 
Alan Modra
Australia Development Lab, IBM


More information about the Binutils mailing list