forked from premiere/premiere-libtorrent
fixed potential hang issue when receiving faster than we can handle the incoming messages
This commit is contained in:
parent
2ac1e69205
commit
18a3d545b0
|
@ -561,11 +561,11 @@ namespace libtorrent
|
||||||
size_type downloaded_since_unchoke() const
|
size_type downloaded_since_unchoke() const
|
||||||
{ return m_statistics.total_payload_download() - m_downloaded_at_last_unchoke; }
|
{ 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:
|
protected:
|
||||||
|
|
||||||
enum sync_t { read_async, read_sync };
|
|
||||||
size_t try_read(sync_t s, error_code& ec);
|
size_t try_read(sync_t s, error_code& ec);
|
||||||
|
|
||||||
virtual void get_specific_peer_info(peer_info& p) const = 0;
|
virtual void get_specific_peer_info(peer_info& p) const = 0;
|
||||||
|
@ -966,6 +966,10 @@ namespace libtorrent
|
||||||
// requesting too many pieces while being choked
|
// requesting too many pieces while being choked
|
||||||
boost::uint8_t m_choke_rejects;
|
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
|
// if this is true, the disconnection
|
||||||
// timestamp is not updated when the connection
|
// timestamp is not updated when the connection
|
||||||
// is closed. This means the time until we can
|
// is closed. This means the time until we can
|
||||||
|
|
|
@ -129,6 +129,7 @@ namespace libtorrent
|
||||||
, m_prefer_whole_pieces(0)
|
, m_prefer_whole_pieces(0)
|
||||||
, m_desired_queue_size(2)
|
, m_desired_queue_size(2)
|
||||||
, m_choke_rejects(0)
|
, m_choke_rejects(0)
|
||||||
|
, m_read_recurse(0)
|
||||||
, m_fast_reconnect(false)
|
, m_fast_reconnect(false)
|
||||||
, m_active(true)
|
, m_active(true)
|
||||||
, m_peer_interested(false)
|
, m_peer_interested(false)
|
||||||
|
@ -266,6 +267,7 @@ namespace libtorrent
|
||||||
, m_prefer_whole_pieces(0)
|
, m_prefer_whole_pieces(0)
|
||||||
, m_desired_queue_size(2)
|
, m_desired_queue_size(2)
|
||||||
, m_choke_rejects(0)
|
, m_choke_rejects(0)
|
||||||
|
, m_read_recurse(0)
|
||||||
, m_fast_reconnect(false)
|
, m_fast_reconnect(false)
|
||||||
, m_active(false)
|
, m_active(false)
|
||||||
, m_peer_interested(false)
|
, m_peer_interested(false)
|
||||||
|
@ -4332,7 +4334,7 @@ namespace libtorrent
|
||||||
m_channel_state[upload_channel] = peer_info::bw_network;
|
m_channel_state[upload_channel] = peer_info::bw_network;
|
||||||
}
|
}
|
||||||
|
|
||||||
void peer_connection::setup_receive()
|
void peer_connection::setup_receive(sync_t sync)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
|
@ -4384,19 +4386,29 @@ namespace libtorrent
|
||||||
// from being at or exceeding the limit down to below the limit
|
// from being at or exceeding the limit down to below the limit
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code ec;
|
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;
|
(*m_logger) << time_now_string() << " *** reached recursion limit\n";
|
||||||
on_receive_data(ec, bytes_transferred);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
try_read(read_async, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t peer_connection::try_read(sync_t s, error_code& ec)
|
size_t peer_connection::try_read(sync_t s, error_code& ec)
|
||||||
|
@ -4680,6 +4692,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
int max_receive = 0;
|
int max_receive = 0;
|
||||||
|
int num_loops = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_VERBOSE_LOGGING
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
|
@ -4731,6 +4744,8 @@ namespace libtorrent
|
||||||
|
|
||||||
if (m_recv_pos >= m_soft_packet_size) m_soft_packet_size = 0;
|
if (m_recv_pos >= m_soft_packet_size) m_soft_packet_size = 0;
|
||||||
|
|
||||||
|
if (num_loops > 20) break;
|
||||||
|
|
||||||
error_code ec;
|
error_code ec;
|
||||||
bytes_transferred = try_read(read_sync, ec);
|
bytes_transferred = try_read(read_sync, ec);
|
||||||
if (ec && ec != asio::error::would_block)
|
if (ec && ec != asio::error::would_block)
|
||||||
|
@ -4741,6 +4756,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
if (ec == asio::error::would_block) break;
|
if (ec == asio::error::would_block) break;
|
||||||
bytes_in_loop += bytes_transferred;
|
bytes_in_loop += bytes_transferred;
|
||||||
|
++num_loops;
|
||||||
}
|
}
|
||||||
while (bytes_transferred > 0);
|
while (bytes_transferred > 0);
|
||||||
|
|
||||||
|
@ -4751,7 +4767,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
m_statistics.trancieve_ip_packet(bytes_in_loop, m_remote.address().is_v6());
|
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
|
bool peer_connection::can_write() const
|
||||||
|
|
Loading…
Reference in New Issue