'Deadlock in __cxa_guard_acquire

First the code:

#pragma once
#include <type_traits>

// assign unique identifiers to types
template<typename ...>
class Family
{
static std::size_t identifier() noexcept
{
  static std::size_t value = 0;
  return value++;
}

template<typename ...>
static std::size_t family() noexcept
{
  static const std::size_t value = identifier();
  return value;
}
public:
using family_type = std::size_t;
template<typename ... Type>
static family_type type() noexcept
{
  return family<std::decay_t<Type>...>();
}
};

// usage
using introspection_family = Family<struct IntrospectionRegistry>;

template<typename Structure>
void addIntrospectData(DataType introspection[MAX_TYPES], DataType const& dataType)
{
  /* reserve index for this type in the introspection register */
  const auto num = introspection_family::type<Structure>();
  assert(num < MAX_TYPES);
  introspection[num - 1] = dataType;
}

This code give an integer to each type and I use it in some kind of C++ introspection implementation.

The application isn't multi threaded. When I compiled it in -O0, sometimes, the call to introspection_family::type<Structure>() blocks at __cxa_guard_acquire@plt and I get a deadlock.

When compiled with -O3, I don't have any problem, but that might just be because it becomes very difficult to reproduce.

__cxa_guard_acquire is used to ensure that the static variable is constructed before we access it but here it should be irrelevant as I'm not even in a threaded application.

Does anyone have any idea why this is happening ?

I use:

CXXFLAGS=-std=c++14 -O0 -g3 -pthread -Wall -Wextra -Werror
LDFLAGS= -g -pthread -lGLEW -lGLU -lGL -lSDL2_mixer -lSDL2 

And I use gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609



Solution 1:[1]

Adding the compile option -fno-threadsafe-statics helped. Since your application is single thread, this is OK.

I had a similar issue. However, the reason in my code was recursion. __cxa_guard_acquire will block when called recursively. A proper fix was needed. I did not check your code if this could also be your problem.

Additional info: The lock used might have a different name than __cxa_guard_acquire. It might also work with recursion, but this is compiler/libc++ specific and you should not rely on that.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1