[asio]how can I wait the last handler return in destructor

Hi all, I have a class class Connection { ... ~Connection() { _socket.close(); } void receiveHandler() { // will crash } tcp::socket _socket; } io_service.run() is called in a working thread, and there are many other sockets runing on the io_service. I call async_read on the _socket, and bind Connection::receiveHandler() as the handler function. Then I delete the Connection object in main thread, the receive operation will be cancelled and the receiveHandler() will be called with errcode boost::asio::error::operation_aborted, but at that time, the Connection object has been deleted, calling receiveHandler() will crash if it access the object's data member. Because there are still other sockets running on the io_service, I can't just join the working thread in Connection's destructor. I want to ensure the socket is closed completely and no more handler will be called in the destructor. One method is create an event before calling _socket.close(), then wait for the event, in receiveHandler(), set the event. Are there any easier method to do this? Thanks, Wang Yun

Hi Wang Yun,
Wang Yun
Then I delete the Connection object in main thread, the receive operation will be cancelled and the receiveHandler() will be called with errcode boost::asio::error::operation_aborted, but at that time, the Connection object has been deleted, calling receiveHandler() will crash if it access the object's data member.
If you're in the destructor and you still have outstanding operations then it's already too late. Your program needs to ensure that any objects referred to by the handler stay valid until the handler is called, and that includes the Connection object referred to by the bound-in `this' pointer.
Are there any easier method to do this?
I find it's usually simplest to use shared_ptr together with enable_shared_from_this to ensure that your Connection object stays alive while there are outstanding operations. Have a look at the Daytime.3 tutorial program for a small example. If you do need the ability to stop a connection, add a member function to your Connection class that closes the socket. When you call this function the operations are cancelled, and the Connection object is destroyed only after all of the associated async operations handlers have been called. Cheers, Chris

Christopher Kohlhoff wrote:
I find it's usually simplest to use shared_ptr together with enable_shared_from_this to ensure that your Connection object stays alive while there are outstanding operations. Have a look at the Daytime.3 tutorial program for a small example.
Yes, shared_ptr is a simple method to avoid delete before using, but it isn't perfect. because it doesn't prevent the object from using other external deleted resource in the handler function. Maybe there is no perfect method for this problem I think.
If you do need the ability to stop a connection, add a member function to your Connection class that closes the socket. When you call this function the operations are cancelled, and the Connection object is destroyed only after all of the associated async operations handlers have been called.
If I call _socket.close() in the same thread which calling io_service.run(), does the handler function always be called before close() return? But if call _socket.close() in main thread, I also don't know when the last handler function will be called and when can delete connection object safely. And in main thread, if I post another function to the io_service after I calling _socket.close(), is this function always be called after last socket handler function is called? Sorry for my poor English, I tried my best to express this clearly. Thanks, Wang Yun
participants (2)
-
Christopher Kohlhoff
-
Wang Yun