diff --git a/libtorrent/include/libtorrent/kademlia/node.hpp b/libtorrent/include/libtorrent/kademlia/node.hpp index ee75e7f0a..d93872db9 100644 --- a/libtorrent/include/libtorrent/kademlia/node.hpp +++ b/libtorrent/include/libtorrent/kademlia/node.hpp @@ -139,9 +139,12 @@ public: void timeout() {} void reply(msg const& r) { - m_rpc.invoke(messages::announce_peer, r.addr - , observer_ptr(new (m_rpc.allocator().malloc()) announce_observer( - m_rpc.allocator(), m_info_hash, m_listen_port, r.write_token))); + observer_ptr o(new (m_rpc.allocator().malloc()) announce_observer( + m_rpc.allocator(), m_info_hash, m_listen_port, r.write_token)); +#ifndef NDEBUG + o->m_in_constructor = false; +#endif + m_rpc.invoke(messages::announce_peer, r.addr, o); m_fun(r.peers, m_info_hash); } void abort() {} diff --git a/libtorrent/include/libtorrent/kademlia/observer.hpp b/libtorrent/include/libtorrent/kademlia/observer.hpp index 141460dc0..073f453bc 100644 --- a/libtorrent/include/libtorrent/kademlia/observer.hpp +++ b/libtorrent/include/libtorrent/kademlia/observer.hpp @@ -56,9 +56,16 @@ struct observer : boost::noncopyable : sent(time_now()) , pool_allocator(p) , m_refs(0) - {} + { +#ifndef NDEBUG + m_in_constructor = true; +#endif + } - virtual ~observer() {} + virtual ~observer() + { + TORRENT_ASSERT(!m_in_constructor); + } // these two callbacks lets the observer add // information to the message before it's sent @@ -79,6 +86,9 @@ struct observer : boost::noncopyable udp::endpoint target_addr; ptime sent; +#ifndef NDEBUG + bool m_in_constructor; +#endif private: boost::pool<>& pool_allocator; // reference counter for intrusive_ptr diff --git a/libtorrent/src/kademlia/closest_nodes.cpp b/libtorrent/src/kademlia/closest_nodes.cpp index 3fbbef07d..7551e806f 100644 --- a/libtorrent/src/kademlia/closest_nodes.cpp +++ b/libtorrent/src/kademlia/closest_nodes.cpp @@ -101,6 +101,9 @@ closest_nodes::closest_nodes( void closest_nodes::invoke(node_id const& id, udp::endpoint addr) { observer_ptr o(new (m_rpc.allocator().malloc()) closest_nodes_observer(this, id, m_target)); +#ifndef NDEBUG + o->m_in_constructor = false; +#endif m_rpc.invoke(messages::find_node, addr, o); } diff --git a/libtorrent/src/kademlia/find_data.cpp b/libtorrent/src/kademlia/find_data.cpp index 5db80fe80..9dc161888 100644 --- a/libtorrent/src/kademlia/find_data.cpp +++ b/libtorrent/src/kademlia/find_data.cpp @@ -110,6 +110,9 @@ void find_data::invoke(node_id const& id, asio::ip::udp::endpoint addr) } observer_ptr o(new (m_rpc.allocator().malloc()) find_data_observer(this, id, m_target)); +#ifndef NDEBUG + o->m_in_constructor = false; +#endif m_rpc.invoke(messages::get_peers, addr, o); } diff --git a/libtorrent/src/kademlia/node.cpp b/libtorrent/src/kademlia/node.cpp index be42c8635..5b919393c 100644 --- a/libtorrent/src/kademlia/node.cpp +++ b/libtorrent/src/kademlia/node.cpp @@ -274,8 +274,11 @@ namespace for (std::vector::const_iterator i = v.begin() , end(v.end()); i != end; ++i) { - rpc.invoke(messages::get_peers, i->addr, observer_ptr( - new (rpc.allocator().malloc()) get_peers_observer(ih, listen_port, rpc, f))); + observer_ptr o(new (rpc.allocator().malloc()) get_peers_observer(ih, listen_port, rpc, f)); +#ifndef NDEBUG + o->m_in_constructor = false; +#endif + rpc.invoke(messages::get_peers, i->addr, o); nodes = true; } } @@ -291,6 +294,9 @@ void node_impl::add_node(udp::endpoint node) // ping the node, and if we get a reply, it // will be added to the routing table observer_ptr o(new (m_rpc.allocator().malloc()) null_observer(m_rpc.allocator())); +#ifndef NDEBUG + o->m_in_constructor = false; +#endif m_rpc.invoke(messages::ping, node, o); } diff --git a/libtorrent/src/kademlia/refresh.cpp b/libtorrent/src/kademlia/refresh.cpp index ce94ca93b..916b6d06a 100644 --- a/libtorrent/src/kademlia/refresh.cpp +++ b/libtorrent/src/kademlia/refresh.cpp @@ -105,6 +105,9 @@ void refresh::invoke(node_id const& nid, udp::endpoint addr) { observer_ptr o(new (m_rpc.allocator().malloc()) refresh_observer( this, nid, m_target)); +#ifndef NDEBUG + o->m_in_constructor = false; +#endif m_rpc.invoke(messages::find_node, addr, o); } @@ -156,6 +159,9 @@ void refresh::invoke_pings_or_finish(bool prevent_request) { observer_ptr o(new (m_rpc.allocator().malloc()) ping_observer( this, node.id)); +#ifndef NDEBUG + o->m_in_constructor = false; +#endif m_rpc.invoke(messages::ping, node.addr, o); ++m_active_pings; ++m_leftover_nodes_iterator; diff --git a/libtorrent/src/kademlia/rpc_manager.cpp b/libtorrent/src/kademlia/rpc_manager.cpp index e4019bab8..7295cf0bf 100644 --- a/libtorrent/src/kademlia/rpc_manager.cpp +++ b/libtorrent/src/kademlia/rpc_manager.cpp @@ -430,6 +430,9 @@ void rpc_manager::reply_with_ping(msg& m) io::write_uint16(m_next_transaction_id, out); observer_ptr o(new (allocator().malloc()) null_observer(allocator())); +#ifndef NDEBUG + o->m_in_constructor = false; +#endif TORRENT_ASSERT(!m_transactions[m_next_transaction_id]); o->sent = time_now(); o->target_addr = m.addr; diff --git a/libtorrent/src/pe_crypto.cpp b/libtorrent/src/pe_crypto.cpp index a865b4c73..d9298e989 100644 --- a/libtorrent/src/pe_crypto.cpp +++ b/libtorrent/src/pe_crypto.cpp @@ -61,8 +61,7 @@ namespace libtorrent TORRENT_ASSERT(sizeof(m_dh_prime) == DH_size(m_DH)); - DH_generate_key(m_DH); - if (m_DH->pub_key == 0) + if (DH_generate_key(m_DH) == 0 || m_DH->pub_key == 0) { DH_free(m_DH); throw std::bad_alloc(); diff --git a/libtorrent/src/peer_connection.cpp b/libtorrent/src/peer_connection.cpp index 0e120e3c8..8afc894de 100755 --- a/libtorrent/src/peer_connection.cpp +++ b/libtorrent/src/peer_connection.cpp @@ -1705,6 +1705,9 @@ namespace libtorrent TORRENT_ASSERT(block.block_index < t->torrent_file().piece_size(block.piece_index)); TORRENT_ASSERT(!t->picker().is_requested(block) || (t->picker().num_peers(block) > 0)); TORRENT_ASSERT(!t->have_piece(block.piece_index)); + TORRENT_ASSERT(std::find(m_download_queue.begin(), m_download_queue.end(), block) == m_download_queue.end()); + TORRENT_ASSERT(std::find(m_request_queue.begin(), m_request_queue.end(), block) == m_request_queue.end()); + piece_picker::piece_state_t state; peer_speed_t speed = peer_speed(); diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp index 209e833c3..a93ad7cb0 100755 --- a/libtorrent/src/session_impl.cpp +++ b/libtorrent/src/session_impl.cpp @@ -1263,10 +1263,21 @@ namespace detail torrent& t = *i->second; if (t.want_more_peers()) { - if (t.try_connect_peer()) + try { - --max_connections; - steps_since_last_connect = 0; + if (t.try_connect_peer()) + { + --max_connections; + steps_since_last_connect = 0; + } + } + catch (std::bad_alloc&) + { + // we ran out of memory trying to connect to a peer + // lower the global limit to the number of peers + // we already have + m_max_connections = num_connections(); + if (m_max_connections < 2) m_max_connections = 2; } } ++m_next_connect_torrent; @@ -2406,8 +2417,10 @@ namespace detail m_buffer_usage_logger << log_time() << " protocol_buffer: " << (m_buffer_allocations * send_buffer_size) << std::endl; #endif - return std::make_pair((char*)m_send_buffers.ordered_malloc(num_buffers) + std::pair ret((char*)m_send_buffers.ordered_malloc(num_buffers) , num_buffers * send_buffer_size); + if (ret.first == 0) throw std::bad_alloc(); + return ret; } void session_impl::free_buffer(char* buf, int size)