Opened 8 years ago

Closed 4 years ago

#3605 closed Bugs (fixed)

Boost.Asio: Static Initialization causes Deadlock during WSAStartup and other problems

Reported by: ulrich.kroemer@… Owned by: chris_kohlhoff
Milestone: Boost 1.41.0 Component: asio
Version: Boost 1.53.0 Severity: Problem
Keywords: deadlock asio WSAStartup Cc:


I am experiencing spurios deadlocks during static initialization of the do_init global instance (win_sock_init.hpp).

The scenario is this: I am using a static library version of Boost.Asio, which means that once my .dll gets loaded, the do_init global instance is initialized and a call to WSAStartup is made.

At the same time a different thread of the application is already in a call to WSAStartup and already holds the critical section inside the WSAStartup function. Now inside that critical section a call to load the old winsock.dll is made and so the other thread tries to gain the loader lock, which my thread currently is the owner of. Therefore the application deadlocks.

I know that this might actually be a problem of WSAStartup all together, however due to the static initialization there is no workaround to the problem, as the time when the call to WSAStartup is made can't be configured.

Attachments (0)

Change History (8)

comment:1 Changed 8 years ago by chris_kohlhoff

Resolution: wontfix
Status: newclosed

I don't plan to make any changes to this area at this time. A possible workaround would be to specialise the winsock_init template:

#include <asio/detail/winsock_init.hpp>

namespace asio
  namespace detail
    template <> class winsock_init<2, 0>

and then manage the winsock initialisation yourself.

comment:2 Changed 7 years ago by jlcastillo@…

Resolution: wontfix
Status: closedreopened
Summary: Boost.Asio: Deadlock during WSAStartupBoost.Asio: Static Initialization causes Deadlock during WSAStartup and other problems
Version: Boost 1.40.0Boost 1.45.0

The static initialization might cause other problems appart from locking. If you divide your project into DLLs, and at least one of them uses Boost Asio, the initialization of static objects and data inside DllMain?(), before main() is called. As you can read from Microsoft documentation:

"Calling functions that require DLLs other than Kernel32.dll may result in problems that are difficult to diagnose. For example, calling User, Shell, and COM functions can cause access violation errors, because some functions load other system components. Conversely, calling functions such as these during termination can cause access violation errors because the corresponding component may already have been unloaded or uninitialized. If your DLL is linked with the C run-time library (CRT), the entry point provided by the CRT calls the constructors and destructors for global and static C++ objects. Therefore, these restrictions for DllMain? also apply to constructors and destructors and any code that is called from them."

Full article:

In our case, we experienced odd behaviour in a program that could run without problems from the command line or as a service. In Windows XP it worked in all cases, while in Windows Vista it only worked from the command line, but not as a service. Unfortunately we were not able to reproduce it with a small fragment of code.

The solution was to comment out the following line in winsock_init.hpp:

//static const winsock_init<>& winsock_init_instance = winsock_init<>(false);

and include the following in our own source code:

#include <boost/asio/detail/winsock_init.hpp>
using namespace boost::asio::detail;
winsock_init<> * winsock_init_instance = NULL;

void BoostAsioInit()
	if(winsock_init_instance == NULL)
		winsock_init_instance = new winsock_init<>(false);

void BoostAsioFinish()
	delete winsock_init_instance;
	winsock_init_instance = NULL;

comment:3 Changed 7 years ago by chris_kohlhoff

Resolution: wontfix
Status: reopenedclosed

Thanks for the additional info. However, please see comment 1.

comment:4 in reply to:  3 Changed 5 years ago by anonymous

Resolution: wontfix
Status: closedreopened
Version: Boost 1.45.0Boost 1.53.0

Replying to chris_kohlhoff:

Thanks for the additional info. However, please see comment 1.

Your comment 1 is wrong.

As long as the line

static const winsock_init<>& winsock_init_instance = winsock_init<>(false);

in winsock_init.hpp exists, there is no way to manage the winsock initialization.

Please make the winsock initialization managable by the user of asio. The static initialization within DllMain? is wrong.

comment:5 Changed 4 years ago by Fedor Trushkin <ted-xp@…>

I happened to encounter this particular issue today. I was surprised that it has been registered several years ago already.

Here are my reasons why this should be considered as a critical issue:

  • as noticed kindly by jlcastillo current library code simply contradicts MSDN documentation;
  • the deadlock under discussion being rarely reproducable has all chances to leak to production;
  • the workaround you proposed is error-prone. Having just a single CPP file with directly included asio libraries will make the whole application buggy;
  • WinSock? initialization will be performed before any consious user actions. Actually, you don't have even to create any of asio-related classes. Just include winsock_init.hpp to any of your cpp files;
  • winsock initialization will be called multiple times: once for every cpp file including winsock_init.hpp. It's not an error, but looks untidy.

I would suggest the following:

  • remove static winsock_init_instance from headers;
  • leave its instances as private member of io_service;
  • require that asio library initialization should be performed before using its classes.

comment:6 Changed 4 years ago by anonymous

Chris, could you at least consider a pre-processor define to disable the static init?

static const winsock_init<>& winsock_init_instance = winsock_init<>(false);

comment:7 Changed 4 years ago by chris_kohlhoff

(In [84877]) Add mechanism for disabling automatic Winsock initialisation. Refs #3605

comment:8 Changed 4 years ago by chris_kohlhoff

Resolution: fixed
Status: reopenedclosed

(In [84895]) Merge from trunk. Fixes #3605.

r84880 | chris_kohlhoff | 2013-06-22 23:02:21 +1000 (Sat, 22 Jun 2013) | 1 line

Revision history.

r84879 | chris_kohlhoff | 2013-06-22 22:58:50 +1000 (Sat, 22 Jun 2013) | 1 line

Regenerate documentation.

r84878 | chris_kohlhoff | 2013-06-22 22:57:51 +1000 (Sat, 22 Jun 2013) | 1 line

Add missing documentation for use_future_t::allocator_type.

r84877 | chris_kohlhoff | 2013-06-22 22:47:44 +1000 (Sat, 22 Jun 2013) | 1 line

Add mechanism for disabling automatic Winsock initialisation. Refs #3605

r84876 | chris_kohlhoff | 2013-06-22 22:45:33 +1000 (Sat, 22 Jun 2013) | 1 line

Fix memory leak in ssl::rfc2818_verification class.

r84875 | chris_kohlhoff | 2013-06-22 22:44:53 +1000 (Sat, 22 Jun 2013) | 1 line

Add support for both boost.coroutine v1 and v2.

Modify Ticket

Change Properties
Set your email in Preferences
as closed The owner will remain chris_kohlhoff.
The resolution will be deleted.

Add Comment

E-mail address and name can be saved in the Preferences.

Note: See TracTickets for help on using tickets.