fixed potential hang issue when receiving faster than we can handle the incoming messages

This commit is contained in:
Arvid Norberg 2010-08-28 19:44:50 +00:00
parent 2ac1e69205
commit 18a3d545b0
2 changed files with 31 additions and 11 deletions

View File

@ -561,11 +561,11 @@ namespace libtorrent
size_type downloaded_since_unchoke() const
{ return m_statistics.total_payload_download() - m_downloaded_at_last_unchoke; }
void setup_receive();
enum sync_t { read_async, read_sync };
void setup_receive(sync_t sync = read_sync);
protected:
enum sync_t { read_async, read_sync };
size_t try_read(sync_t s, error_code& ec);
virtual void get_specific_peer_info(peer_info& p) const = 0;
@ -966,6 +966,10 @@ namespace libtorrent
// requesting too many pieces while being choked
boost::uint8_t m_choke_rejects;
// counts the number of recursive calls to on_receive_data
// used to limit recursion
boost::uint8_t m_read_recurse:5;
// if this is true, the disconnection
// timestamp is not updated when the connection
// is closed. This means the time until we can

View File

@ -129,6 +129,7 @@ namespace libtorrent
, m_prefer_whole_pieces(0)
, m_desired_queue_size(2)
, m_choke_rejects(0)
, m_read_recurse(0)
, m_fast_reconnect(false)
, m_active(true)
, m_peer_interested(false)
@ -266,6 +267,7 @@ namespace libtorrent
, m_prefer_whole_pieces(0)
, m_desired_queue_size(2)
, m_choke_rejects(0)
, m_read_recurse(0)
, m_fast_reconnect(false)
, m_active(false)
, m_peer_interested(false)
@ -4332,7 +4334,7 @@ namespace libtorrent
m_channel_state[upload_channel] = peer_info::bw_network;
}
void peer_connection::setup_receive()
void peer_connection::setup_receive(sync_t sync)
{
INVARIANT_CHECK;
@ -4384,19 +4386,29 @@ namespace libtorrent
// from being at or exceeding the limit down to below the limit
return;
}
error_code ec;
size_t bytes_transferred = try_read(read_sync, ec);
if (ec == asio::error::would_block)
if (sync == read_sync && m_read_recurse < 10)
{
try_read(read_async, ec);
size_t bytes_transferred = try_read(read_sync, ec);
if (ec != asio::error::would_block)
{
++m_read_recurse;
m_channel_state[download_channel] = peer_info::bw_network;
on_receive_data(ec, bytes_transferred);
--m_read_recurse;
return;
}
}
else
#ifdef TORRENT_VERBOSE_LOGGING
if (m_read_recurse >= 10)
{
m_channel_state[download_channel] = peer_info::bw_network;
on_receive_data(ec, bytes_transferred);
(*m_logger) << time_now_string() << " *** reached recursion limit\n";
}
#endif
try_read(read_async, ec);
}
size_t peer_connection::try_read(sync_t s, error_code& ec)
@ -4680,6 +4692,7 @@ namespace libtorrent
}
int max_receive = 0;
int num_loops = 0;
do
{
#ifdef TORRENT_VERBOSE_LOGGING
@ -4731,6 +4744,8 @@ namespace libtorrent
if (m_recv_pos >= m_soft_packet_size) m_soft_packet_size = 0;
if (num_loops > 20) break;
error_code ec;
bytes_transferred = try_read(read_sync, ec);
if (ec && ec != asio::error::would_block)
@ -4741,6 +4756,7 @@ namespace libtorrent
}
if (ec == asio::error::would_block) break;
bytes_in_loop += bytes_transferred;
++num_loops;
}
while (bytes_transferred > 0);
@ -4751,7 +4767,7 @@ namespace libtorrent
}
m_statistics.trancieve_ip_packet(bytes_in_loop, m_remote.address().is_v6());
setup_receive();
setup_receive(read_async);
}
bool peer_connection::can_write() const