chriskohlhoff / asio

Asio C++ Library
http://think-async.com/Asio
4.97k stars 1.22k forks source link

static member `boost::asio::detail::call_stack<...>::top_` is not unique at runtime, in mingw64 environment. #780

Open goulf-3m opened 3 years ago

goulf-3m commented 3 years ago

Non-uniqueness makes running_in_this_thread() calls useless, when multiple shared libraries are used.

The Asio library is used in this way:

  1. a cpp file containing #include <boost/asio/impl/src.hpp> is compiled into a shared library, libX;
  2. another shared library, libY, uses Asio codes and links to libX;
  3. an executable, Z, uses Asio codes and links to libX and libY.

Compilation flags are set correctly according to Asio docs. In Linux, everything works fine: top_ has unique global linkage (GNU extension).

In Windows, libX, libY and Z each has it's copy of top_. If a thread registers itself in call stack by calling a function in libX, then calling running_in_this_thread() in the same thread in a function in libY or Z will return FALSE. Insertions and queries may not be applied with the same linked list!

I can fix this by inserting the following code in to source files in libY and Z:

if defined(_WIN32)

namespace boost::asio::detail { template<typename,typename> class __declspec(dllimport) call_stack; }

endif

NOTE: the condition is made with _WIN32, not _MSC_VER (boost/asio/detail/config.hpp uses this to enable export/import), because mingw64 gcc compiler needs this fix too.

ALSO: the same problem occurs in old versions of Android systems.

I suggest using a plain class for this (so the static member definition is not in the header file), or add __dllspec(dllimport) to disable generating copies of definition in user code, or use extern template ... declarations (not quite sure).

ichorate commented 3 years ago

I think i have a problem relate to this issue.

When i spawn a coroutine via different dll it cause the io_context run forever.

The condtion seems to be. 1 Use old io_context_strand.

  1. Strand Implementation hash collision occured.
  2. Spawn a coroutine via different dll.

Example code: test_asio.zip

Environment: