[ASIO] Access violation on io_service::work destructor

Hi, In my code I have a io_Service and a work object shared among my classes: // Main io_service static boost::asio::io_service io_service; static boost::scoped_ptrboost::thread io_service_thread; static boost::asio::io_service::work* p_work; static BOOL thread_started; void io_worker_thread(void) { #if(WIN32 && _WIN32_DCOM) struct com_init { com_init() { CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); } ~com_init() { CoUninitialize(); } } initializer_object; #endif io_service.run(); io_service.reset(); thread_started = false; }; void Init(....) { if (!thread_started) { try { // create the work object on the heap p_work = new boost::asio::io_service::work(io_service); // run the IO service as a separate thread: // Instead of start the worker thread directly // by passing the io_service object, // I call the io_worker_thread function where // I can do some initialization tasks like // calling CoInitializeEx for COM io_service_thread.reset(new boost::thread(io_worker_thread)); thread_started = !thread_started; } catch (boost::thread_resource_error e) { // Failed to create the new thread return 0; } } } When my application ends and the io_service.run() returns I get: First-chance exception at 0x09299c18 (AxEuroATLib_debug.dll) in EuroSvr.exe: 0xC0000005: Access violation reading location 0xf0f0f0fc. at the following line (io_service.ipp): inline io_service::work::~work() { io_service_.impl_.work_finished(); } I wrong something? Regards, Daniele

On 2010-09-23 10:51, Daniele Barzotti wrote:
Hi,
In my code I have a io_Service and a work object shared among my classes:
[snip]
When my application ends and the io_service.run() returns I get:
First-chance exception at 0x09299c18 (AxEuroATLib_debug.dll) in EuroSvr.exe: 0xC0000005: Access violation reading location 0xf0f0f0fc.
at the following line (io_service.ipp):
inline io_service::work::~work() { io_service_.impl_.work_finished(); }
I wrong something?
Regards, Daniele
Besides a possible race in your statement thread_started = !thread_started; and some other bad stuff such as memory leaks when throwing an exception, I don't see where the destructor of the work object is called. Could you provide the code involved? Rutger

Il 23/09/2010 11:18, Rutger ter Borg ha scritto:
Besides a possible race in your statement
thread_started = !thread_started;
and some other bad stuff such as memory leaks when throwing an exception, I don't see where the destructor of the work object is called. Could you provide the code involved?
Hi Rutger, thanks for your reply. Why ' thread_started = !thread_started; ' is a bad stuff? Now, when I crate an object that use io_service, I assign the pointer to io_service::work to a shared_pointer: typedef boost::shared_ptrboost::asio::io_service::work io_work_ptr; EXTERN_C DLL_EXPORT MyObjectHandle CALL GetMyObj() { if (!thread_started) { try { // create the work object on the heap p_work = new boost::asio::io_service::work(io_service); // run the IO service as a separate thread: io_service_thread.reset(new boost::thread(io_worker_thread)); thread_started = !thread_started; } catch (boost::thread_resource_error e) { // Failed to create the new thread return 0; } } // create the new object MyObject* pMyObject = new MyObject(io_service); // Assign a reference to io_service work object: // This reference is used to counting the objects created. // When the last MyObject is deleted the main work object // is destroyed and the io_service thread ends. pMyObject->_io_work_ptr.reset(p_work); // return the object return pMyObject; }; Mmmm, now I'm thinking about, I have this issue only if I create more than 1 object... Regards, Daniele.

On 2010-09-23 12:00, Daniele Barzotti wrote:
Why ' thread_started = !thread_started; ' is a bad stuff?
From what I could see (not knowing where the work object is deallocated), the worker thread could have finished before this statement is executed. The thing I referred to as being 'bad stuff' was the allocation of a work object which is not being deallocated when the thread didn't start properly. [snip]
pMyObject->_io_work_ptr.reset(p_work); [/snip]
I guess all your pMyObjects have shared pointers with a reference count of 1; you reset them all with a plain pointer (p_work). Regards, Rutger

Il 23/09/2010 14:37, Rutger ter Borg wrote:
Why ' thread_started = !thread_started; ' is a bad stuff?
(not knowing where the work object is deallocated)
In my intention the work object should be deallocated automatically when the referent count of the shared_ptr is 0.
the worker thread could have finished before this statement is executed. The thing I referred to as being 'bad stuff' was the allocation of a work object which is not being deallocated when the thread didn't start properly.
[snip]
pMyObject->_io_work_ptr.reset(p_work); [/snip]
I guess all your pMyObjects have shared pointers with a reference count of 1; you reset them all with a plain pointer (p_work).
Ops..you're right!! I change my code with the following and now all seems to work as expected! typedef boost::shared_ptrboost::asio::io_service::work io_work_ptr; static io_work_ptr pWork; EXTERN_C DLL_EXPORT MyObjectHandle CALL GetMyObj() { if (!thread_started) { try { // create the work object on the heap p_work.reset( new boost::asio::io_service::work(io_service) ); // run the IO service as a separate thread: io_service_thread.reset(new boost::thread(io_worker_thread)); thread_started = !thread_started; } catch (boost::thread_resource_error e) { // Failed to create the new thread return 0; } } // create the new object MyObject* pMyObject = new MyObject(io_service); // Assign a reference to io_service work object: // This reference is used to counting the objects created. // When the last MyObject is deleted the main work object // is destroyed and the io_service thread ends. pMyObject->_io_work_ptr = p_work; // return the object return pMyObject; };

On 2010-09-23 15:28, Daniele Barzotti wrote:
Ops..you're right!!
I change my code with the following and now all seems to work as expected!
That's odd. You are using a static shared pointer, so I would expect the reference count of pwork to be #objects + 1, not #objects. Regards, Rutger

Il 23/09/2010 15:52, Rutger ter Borg ha scritto:
On 2010-09-23 15:28, Daniele Barzotti wrote:
Ops..you're right!!
I change my code with the following and now all seems to work as expected!
That's odd. You are using a static shared pointer, so I would expect the reference count of pwork to be #objects + 1, not #objects.
Yes, but in my previous implementation I have created a plain pointer and assigned to a shared_pointer through the reset() method which reset all previous counting, so I had more shared_ptr "not really shared" :-) Cheers, Daniele.
participants (2)
-
Daniele Barzotti
-
Rutger ter Borg