possible dangling pointer fix in broadcast_socket

This commit is contained in:
Arvid Norberg 2011-10-25 05:55:32 +00:00
parent b80aa035a2
commit 0a2b352795
3 changed files with 42 additions and 5 deletions

View File

@ -117,6 +117,9 @@ namespace libtorrent
void open_multicast_socket(io_service& ios, address const& addr void open_multicast_socket(io_service& ios, address const& addr
, bool loopback, error_code& ec); , bool loopback, error_code& ec);
// if we're aborting, destruct the handler and return true
bool maybe_abort();
// these sockets are used to // these sockets are used to
// join the multicast group (on each interface) // join the multicast group (on each interface)
// and receive multicast messages // and receive multicast messages
@ -128,6 +131,18 @@ namespace libtorrent
std::list<socket_entry> m_unicast_sockets; std::list<socket_entry> m_unicast_sockets;
udp::endpoint m_multicast_endpoint; udp::endpoint m_multicast_endpoint;
receive_handler_t m_on_receive; receive_handler_t m_on_receive;
// the number of outstanding async operations
// we have on these sockets. The m_on_receive
// handler may not be destructed until this reaches
// 0, since it may be holding references to
// the broadcast_socket itself.
int m_outstanding_operations;
// when set to true, we're trying to shut down
// don't initiate new operations and once the
// outstanding counter reaches 0, destruct
// the handler object
bool m_abort;
}; };
} }

View File

@ -217,6 +217,8 @@ namespace libtorrent
, bool loopback) , bool loopback)
: m_multicast_endpoint(multicast_endpoint) : m_multicast_endpoint(multicast_endpoint)
, m_on_receive(handler) , m_on_receive(handler)
, m_outstanding_operations(0)
, m_abort(false)
{ {
TORRENT_ASSERT(is_multicast(m_multicast_endpoint.address())); TORRENT_ASSERT(is_multicast(m_multicast_endpoint.address()));
@ -279,6 +281,7 @@ namespace libtorrent
#endif #endif
s->async_receive_from(asio::buffer(se.buffer, sizeof(se.buffer)) s->async_receive_from(asio::buffer(se.buffer, sizeof(se.buffer))
, se.remote, boost::bind(&broadcast_socket::on_receive, this, &se, _1, _2)); , se.remote, boost::bind(&broadcast_socket::on_receive, this, &se, _1, _2));
++m_outstanding_operations;
} }
void broadcast_socket::open_unicast_socket(io_service& ios, address const& addr void broadcast_socket::open_unicast_socket(io_service& ios, address const& addr
@ -305,6 +308,7 @@ namespace libtorrent
#endif #endif
s->async_receive_from(asio::buffer(se.buffer, sizeof(se.buffer)) s->async_receive_from(asio::buffer(se.buffer, sizeof(se.buffer))
, se.remote, boost::bind(&broadcast_socket::on_receive, this, &se, _1, _2)); , se.remote, boost::bind(&broadcast_socket::on_receive, this, &se, _1, _2));
++m_outstanding_operations;
} }
void broadcast_socket::send(char const* buffer, int size, error_code& ec, int flags) void broadcast_socket::send(char const* buffer, int size, error_code& ec, int flags)
@ -365,14 +369,31 @@ namespace libtorrent
#if defined TORRENT_ASIO_DEBUGGING #if defined TORRENT_ASIO_DEBUGGING
complete_async("broadcast_socket::on_receive"); complete_async("broadcast_socket::on_receive");
#endif #endif
if (ec || bytes_transferred == 0 || !m_on_receive) return; TORRENT_ASSERT(m_outstanding_operations > 0);
--m_outstanding_operations;
if (ec || bytes_transferred == 0 || !m_on_receive)
{
maybe_abort();
return;
}
m_on_receive(s->remote, s->buffer, bytes_transferred); m_on_receive(s->remote, s->buffer, bytes_transferred);
if (maybe_abort()) return;
if (!s->socket) return; if (!s->socket) return;
#if defined TORRENT_ASIO_DEBUGGING #if defined TORRENT_ASIO_DEBUGGING
add_outstanding_async("broadcast_socket::on_receive"); add_outstanding_async("broadcast_socket::on_receive");
#endif #endif
s->socket->async_receive_from(asio::buffer(s->buffer, sizeof(s->buffer)) s->socket->async_receive_from(asio::buffer(s->buffer, sizeof(s->buffer))
, s->remote, boost::bind(&broadcast_socket::on_receive, this, s, _1, _2)); , s->remote, boost::bind(&broadcast_socket::on_receive, this, s, _1, _2));
++m_outstanding_operations;
}
bool broadcast_socket::maybe_abort()
{
if (m_abort && m_outstanding_operations == 0)
m_on_receive.clear();
return m_abort;
} }
void broadcast_socket::close() void broadcast_socket::close()
@ -380,7 +401,8 @@ namespace libtorrent
std::for_each(m_sockets.begin(), m_sockets.end(), boost::bind(&socket_entry::close, _1)); std::for_each(m_sockets.begin(), m_sockets.end(), boost::bind(&socket_entry::close, _1));
std::for_each(m_unicast_sockets.begin(), m_unicast_sockets.end(), boost::bind(&socket_entry::close, _1)); std::for_each(m_unicast_sockets.begin(), m_unicast_sockets.end(), boost::bind(&socket_entry::close, _1));
m_on_receive.clear(); m_abort = true;
maybe_abort();
} }
} }

View File

@ -1598,9 +1598,9 @@ namespace aux {
m_i2p_conn.close(ec); m_i2p_conn.close(ec);
#endif #endif
m_queued_for_checking.clear(); m_queued_for_checking.clear();
if (m_lsd) m_lsd->close(); stop_lsd();
if (m_upnp) m_upnp->close(); stop_upnp();
if (m_natpmp) m_natpmp->close(); stop_natpmp();
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
if (m_dht) if (m_dht)
{ {