[asio] io_service use in dll leads to service_registry crash
Configuration: 1) Boost 1.37 2) Visual Studio 2008 3) Windows executable using boost's multi-threaded static library, using a static linked multi-threaded run time. 4) A dll I have as part of the project is compiled with the same settings. 5) MFC is not used. The executable creates an io_service (io) and pool of worker threads, each calling io.run(). Afterwards, the executable begins loading DLLs I've written to add specific functionality (i.e plugins). Each of these plugins are passed the executable's io_service so that they can perform asynchronous work against the thread pool. One of the DLLs creates a boost::asio::ip::tcp::acceptor object, passing the io_service to its constructor. This, in turn, eventually calls use_service, which creates a new service and associates it with the service_registry. This is all happening in the DLL. At shut down, I begin unloading the DLLs, giving each a chance to shut down everything (which they do). I then call FreeLibrary() on the DLL's HMODULE handle. After my application completes shutdown, all the destructors hit, as expected. When the destructor of the service_registry hits, I believe its linked list of services is still pointing to a service located in the memory space of the DLL. This results in a crash. I believe this is the case as I can track the pointer to the acceptor_service in a Watch Window. The pointers and the object remain valid until I call "FreeLibrary", at which point they become worthless. I think this is because the DLL and the executable have their own CRT memory space, due to the way I'm linking in the CRT. The service for the acceptor is being created in the DLL's space. When FreeLibrary is called, this space is released to the OS, making the pointer to the object worthless. If that's the case, I believe I'll need to supply my own service creation routine for the DLLs so that the services are created in my executable's memory space. Is this possible? Is there a way to get the service_registry to release a service when it's no longer in use anywhere, or to specify my own new/delete routines the use_service calls should use? Or, is using ASIO in a DLL like this a really really bad idea? If that's the case, how can I tell what other objects in boost could cause these sorts of problems? I'll try to get a project together that reproduces the issue as soon as I can. I can't use the code I have at the moment as it is proprietary. Thanks for any input anyone can provide. -- View this message in context: http://www.nabble.com/-asio--io_service-use-in-dll-leads-to-service_registry... Sent from the Boost - Users mailing list archive at Nabble.com.
joshr wrote:
I'll try to get a project together that reproduces the issue as soon as I can. I can't use the code I have at the moment as it is proprietary.
I've attached a zip of the Visual Studio 2008 solution and project files that reproduces the issue. The bin folder contains the compiled executable as well, if for some reason this is useful. If you need to recreate the projects for another version of studio, here are the settings I've used: Solution (Folder for solution): Project asiodll (Windows Console Application) Project extension (Windows DLL) Both Projects have the following settings (Everything else is default): Output Directory: $(SolutionDir)bin Character Set: Use Multibyte Character Set Code Generation (Release): Multi-Threaded (/MT) Code Generation (Debug): Multi-Threaded Debug (/MTd) Preprocessor Definitions: STRICT and WIN32_LEAN_AND_MEAN were added Generate Manifest: No File: http://www.nabble.com/file/p22062206/asiodll.zip asiodll.zip -- View this message in context: http://www.nabble.com/-asio--io_service-use-in-dll-leads-to-service_registry... Sent from the Boost - Users mailing list archive at Nabble.com.
I've attached a zip of the Visual Studio 2008 solution and project files that reproduces the issue. The bin folder contains the compiled executable as well, if for some reason this is useful.
I built and run your code. It really crashes if you forcibly unload the dll but it does *not* crash if I comment-out this line *or* if I remove acceptor object from the dll code. It seems that the reason of the crash is that a dll statically linked to CRT has its own private CRT (including memmoty management), so when you free the dll, all the asio objects created from within the dll (asio services in this case) become inaccessible. Try and build asio, dll and the host app with dynamic CRT - probably this will help.
Igor R wrote:
I built and run your code. It really crashes if you forcibly unload the dll but it does *not* crash if I comment-out this line *or* if I remove acceptor object from the dll code. It seems that the reason of the crash is that a dll statically linked to CRT has its own private CRT (including memmoty management), so when you free the dll, all the asio objects created from within the dll (asio services in this case) become inaccessible. Try and build asio, dll and the host app with dynamic CRT - probably this will help.
This was the same behavior I saw as well after further testing and came to the same conclusions. Ultimately I want to hide the Boost interface from plugin developers so that I don't require the use of Boost. For this initial implementation, which I have to write, I was hoping to pass the boost objects as a temporary stepping stone. At any rate, thank you very much for your feedback! It definitely gives me some things to rethink in my design. -- View this message in context: http://www.nabble.com/-asio--io_service-use-in-dll-leads-to-service_registry... Sent from the Boost - Users mailing list archive at Nabble.com.
participants (2)
-
Igor R
-
joshr