[ASIO] Safely shut down timer thread in boost::asio::io_service in Windows DLL
Hi folks,
As you might already know, Windows DLL has quite some limitation about what
you can do during its loading and unloading. For example, you can't 'join'
a thread when unloading a DLL. The consequence of doing that, from my
opinion, is quite serious: it will hang the process in a dead lock.
I have a Windows DLL, which uses boost::asio::deadline_timer. I found that
deadline_timer::async_wait creates a timer thread as a private member of
io_service. This thread won't be shut down even if all the timers are
cancelled. In the destructor of io_service, 'join' will be called on the
thread. In some exceptional situation, users might exit their main function
before destructs the io_service inside my DLL, so the destructor is called
during the unloading of the DLL, which hangs their process.
The following code demonstrates this issue. action.h and action.cpp are the
code for the dll, main.cpp are the code for the application which uses the
dll.
action.h:
#pragma once
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
extern "C" __declspec(dllexport) void start();
extern "C" __declspec(dllexport) void stop();
action.cpp:
#include "action.h"
#include
On Oct 1, 2013, at 10:22, Bo Peng wrote:
I have a Windows DLL, which uses boost::asio::deadline_timer. I found that deadline_timer::async_wait creates a timer thread as a private member of io_service. This thread won't be shut down even if all the timers are cancelled. In the destructor of io_service, 'join' will be called on the thread. In some exceptional situation, users might exit their main function before destructs the io_service inside my DLL, so the destructor is called during the unloading of the DLL, which hangs their process.
boost::shared_ptr<Action> action;
In my opinion, the solution here is to not destroy this object automatically on unload. Turn it into a raw pointer. In the exceptional situation, you'll leak the object and the I/O service and the thread, but since the user is about to exit the main function (at least from your description), the process will terminate anyway. You could add a line to DllMain's PROCESS_DETACH that checks whether the pointer is non-null and prints a warning message to the debug log if you want the user to have a chance to know about this happening. Sebastian
Hi Sebastian, Thanks for your reply. You solution will definitely work for my case.
From a defensive programming point of view, it would still be nice to automatically clean all the resource during dll unloading, and it would be useful if user unloads the dll but doesn't shut down the process. But I'll leave this to the boost developers.
Regards,
Bo
On 3 October 2013 21:25, Sebastian Redl
On Oct 1, 2013, at 10:22, Bo Peng wrote:
I have a Windows DLL, which uses boost::asio::deadline_timer. I found
that
deadline_timer::async_wait creates a timer thread as a private member of io_service. This thread won't be shut down even if all the timers are cancelled. In the destructor of io_service, 'join' will be called on the thread. In some exceptional situation, users might exit their main function before destructs the io_service inside my DLL, so the destructor is called during the unloading of the DLL, which hangs their process.
boost::shared_ptr<Action> action;
In my opinion, the solution here is to not destroy this object automatically on unload. Turn it into a raw pointer. In the exceptional situation, you'll leak the object and the I/O service and the thread, but since the user is about to exit the main function (at least from your description), the process will terminate anyway.
You could add a line to DllMain's PROCESS_DETACH that checks whether the pointer is non-null and prints a warning message to the debug log if you want the user to have a chance to know about this happening.
Sebastian
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
participants (2)
-
Bo Peng
-
Sebastian Redl