t.g.
t.g.

Reputation: 1749

is it safe to to destroy a socket object while an asyn_read might be going on in boost.ASIO?

In the following code:

tcp::socket socket(io_service);
tcp::endpoint ep(boost::asio::ip::address::from_string(addr), i);


socket.async_connect(ep, &connect_handler);

socket.close();

is it correct to close the socket object, or should I close it only in the connect_handler(), resort to shared_ptr to prolong the life of of the socket object? Thanks.

Upvotes: 4

Views: 1857

Answers (3)

karunski
karunski

Reputation: 4090

Closing the socket isn't much of an issue, but the socket being destructed and deallocated is. One way to deal with it is to just make sure the socket outlives the io_service where work is being done. In other words, you just make sure to not delete it until after the io_service has exited. Obviously this won't work in every situation.

In a variety of conditions it can be difficult to impossible to tell when all work is really done on the socket when it's active within the io_service, and ASIO doesn't provide any mechanism to explicitly remove or disconnect the object's callbacks so they don't get called. So you should consider holding the connection in a shared_ptr, which will keep the connection object until the last reference inside the io_service has been released.

Meanwhile your handler functors should handle all possible errors passed in, including the connection being destroyed.

Upvotes: 3

jweyrich
jweyrich

Reputation: 32250

As already answered by Chila, it's safe to close the socket whenever you want. If the socket in question has an outstanding operation at the time, the handler/callback will be invoked to notify you've cancelled the operation. That's where connection_aborted shows up.

As for your question about shared_ptr, I consider it a big win if you have another thread or other objects referencing your sockets, however, it isn't required in many cases. All you have to do is to dynamically allocate them, and deallocate when they're no longer needed. Of course, if you have other objects or threads referencing your socket, you must update them prior to delete/dealloc. Doing so, you avoid invalid memory access because the object pointed by them no longer exists (see dangling pointer).

Upvotes: 1

chila
chila

Reputation: 2442

It is safe. The connect_handler will give you ec == boost::asio::error::connection_aborted. Of course, you need to do io_service.run() for the handler to be invoked.

Upvotes: 1

Related Questions