Opened 13 years ago
Closed 9 years ago
#3605 closed Bugs (fixed)
Boost.Asio: Static Initialization causes Deadlock during WSAStartup and other problems
Reported by: | Owned by: | chris_kohlhoff | |
---|---|---|---|
Milestone: | Boost 1.41.0 | Component: | asio |
Version: | Boost 1.53.0 | Severity: | Problem |
Keywords: | deadlock asio WSAStartup | Cc: |
Description
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.
Change History (8)
comment:1 by , 13 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
comment:2 by , 12 years ago
Resolution: | wontfix |
---|---|
Status: | closed → reopened |
Summary: | Boost.Asio: Deadlock during WSAStartup → Boost.Asio: Static Initialization causes Deadlock during WSAStartup and other problems |
Version: | Boost 1.40.0 → Boost 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: http://msdn.microsoft.com/en-us/library/ms682583(VS.85).aspx
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; }
follow-up: 4 comment:3 by , 12 years ago
Resolution: | → wontfix |
---|---|
Status: | reopened → closed |
Thanks for the additional info. However, please see comment 1.
comment:4 by , 10 years ago
Resolution: | wontfix |
---|---|
Status: | closed → reopened |
Version: | Boost 1.45.0 → Boost 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 by , 9 years ago
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 by , 9 years ago
Chris, could you at least consider a pre-processor define to disable the static init?
#ifndef BOOST_ASIO_NO_WINSOCKINIT static const winsock_init<>& winsock_init_instance = winsock_init<>(false); #endif
comment:7 by , 9 years ago
comment:8 by , 9 years ago
Resolution: | → fixed |
---|---|
Status: | reopened → closed |
(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.
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:
and then manage the winsock initialisation yourself.