Description
When dont_count_slow_torrents is enabled, libtorrent may start additional auto-managed downloads even though an already-running torrent is transferring far above inactive_down_rate.
This is visible in qBittorrent with the following configuration:
- Maximum active downloads:
1
- Do not count slow torrents in these limits: enabled
- Download-rate threshold:
10 KiB/s
- Torrent inactivity timer: any nonzero value
A torrent downloading continuously at approximately 10 MiB/s should clearly count toward the active-download limit, but another queued torrent is nevertheless started.
Related downstream reports:
- qBittorrent issue #20647: queueing limit is exceeded while torrents are above the slow threshold
- qBittorrent issue #21284: enabling “Do not count slow torrents” may start every torrent in the queue
No equivalent current libtorrent issue appears to exist.
Expected behavior
With:
active_downloads = 1
dont_count_slow_torrents = true
inactive_down_rate = 10 KiB/s
the behavior should be:
- Torrent A starts downloading.
- If Torrent A stays below the inactivity thresholds for the configured interval, it stops counting toward
active_downloads.
- Torrent B may then start.
- As soon as Torrent A resumes transferring above the threshold, Torrent A should count toward
active_downloads again.
- The auto-manager should restore the configured active-download limit, normally by pausing the lower-priority torrent.
A torrent downloading at several MiB/s should never remain exempt from active_downloads.
Actual behavior
Torrent A may be downloading at approximately 10 MiB/s, while Torrent B is also started despite:
active_downloads = 1
inactive_down_rate = 10 KiB/s
In some cases, many or all queued torrents may start.
Steps to reproduce
- Create a libtorrent session with approximately these settings:
settings_pack settings;
settings.set_int(settings_pack::active_downloads, 1);
settings.set_bool(settings_pack::dont_count_slow_torrents, true);
settings.set_int(settings_pack::inactive_down_rate, 10 * 1024);
settings.set_int(settings_pack::inactive_up_rate, 1 * 1024);
settings.set_int(settings_pack::auto_manage_startup, 60);
- Add at least two incomplete torrents as auto-managed torrents.
- Allow Torrent A to begin downloading.
- Verify that Torrent A’s payload download rate remains well above
inactive_down_rate, for example 10 MiB/s.
- Observe whether Torrent B is also unpaused by the auto-manager.
- Optionally begin with Torrent A inactive, then allow it to acquire peers and resume at a high rate.
Suspected cause
The qBittorrent side appears to pass the configured threshold to libtorrent correctly. For example, a configured value of 10 KiB/s is passed as approximately 10,240 bytes/s.
The likely issue is libtorrent’s cached inactive state, m_inactive, and how it interacts with auto-management.
The auto-manager exempts torrents for which torrent::is_inactive() is true from the active_downloads and active_seeds limits. This is expected while a torrent is genuinely inactive.
However, the inactive state appears to be debounced for both state transitions:
active -> inactive
inactive -> active
Using the inactivity interval for the first transition makes sense: a short transfer-rate dip should not immediately free an active slot.
Using the same delay for the reverse transition is problematic. Once an inactive torrent begins transferring above the configured threshold, it can continue to report is_inactive() == true until the inactivity timer expires.
During that interval, the torrent can transfer at a high rate while still being excluded from active_downloads. The auto-manager may consequently start another queued torrent.
There may be a second related issue when dont_count_slow_torrents is enabled or its settings are updated. An auto-managed torrent that is paused because it is queued naturally has a payload rate of zero. If such torrents are evaluated as inactive before they have been allowed to run, they may be preclassified as exempt from the active-download limit. The auto-manager can then unpause multiple queued torrents.
In other words, the problematic sequence may be:
queued torrent
-> zero transfer rate
-> classified inactive
-> exempt from active_downloads
-> unpaused by auto-manager
-> transfers above threshold
-> remains classified inactive during recovery delay
-> another queued torrent is also started
Suggested fix
1. Clear the inactive state immediately on recovery
The delay should apply when determining that a torrent has become inactive, but not when determining that it has become active again.
Conceptually:
bool const currentlySlow =
payloadDownloadRate < inactiveDownRate
&& payloadUploadRate < inactiveUpRate;
if (!m_inactive)
{
if (currentlySlow)
{
// Start or continue the inactivity timer.
// Set m_inactive only after the configured interval.
}
else
{
// Cancel/reset any pending inactivity timer.
}
}
else
{
if (!currentlySlow)
{
// Recovery should be immediate.
m_inactive = false;
trigger_auto_manage();
}
}
This preserves protection against brief low-rate periods while ensuring that a torrent transferring above the threshold immediately counts against the queue limits.
2. Do not classify queued/paused torrents as inactive based solely on zero rate
A torrent paused by the auto-manager because it is queued has no meaningful transfer rate. Its zero rate should not cause it to be marked inactive before it has been started.
Possible approaches include:
if (is_paused())
return false;
or restricting inactivity accounting to torrents that are:
- auto-managed;
- currently unpaused;
- in a downloading or seeding state; and
- have had an opportunity to transfer for the configured interval.
The exact condition may need to distinguish a user-paused torrent from one paused by auto-management.
3. Re-run auto-management when inactivity is cleared
When m_inactive changes from true to false, auto-management should be triggered promptly so that active_downloads is enforced again.
Otherwise, even after the state is corrected, too many downloads may remain active until some unrelated event causes another auto-management pass.
Suggested regression tests
Recovered torrent counts immediately
- Set
active_downloads = 1.
- Enable
dont_count_slow_torrents.
- Make Torrent A inactive long enough for Torrent B to start.
- Increase Torrent A’s payload rate above
inactive_down_rate.
- Verify immediately, or on the next management tick, that no more than one torrent remains active.
High-rate torrent never frees its slot
- Set
active_downloads = 1.
- Keep Torrent A above
inactive_down_rate.
- Wait longer than
auto_manage_startup.
- Verify that Torrent B remains queued.
Queued torrents are not preclassified inactive
- Add several auto-managed incomplete torrents.
- Set
active_downloads = 1.
- Enable
dont_count_slow_torrents.
- Verify that queued torrents are not all unpaused merely because their current rate is zero.
Brief rate dip does not free a slot
- Keep Torrent A below the threshold for less than
auto_manage_startup.
- Verify that Torrent B remains queued.
- Restore Torrent A above the threshold.
- Verify that the pending inactivity transition is canceled.
Additional diagnostic suggestion
It may help to log the following during an auto-management pass:
torrent name/hash
paused
auto_managed
payload download rate
payload upload rate
m_inactive
time in candidate inactive state
whether it consumed active_downloads
auto-management action
That should confirm whether the high-rate torrent is still carrying a stale inactive flag when the additional torrent is started.
Environment
Observed through qBittorrent 5.1.x using libtorrent 2.0.x.
The exact libtorrent version can be added from qBittorrent’s:
Help -> About -> Software used
Notes
The source-level cause described above is a hypothesis based on the inactivity and auto-management paths. A minimal libtorrent-only reproduction or temporary logging of m_inactive transitions would be useful to confirm it.
Description
When
dont_count_slow_torrentsis enabled, libtorrent may start additional auto-managed downloads even though an already-running torrent is transferring far aboveinactive_down_rate.This is visible in qBittorrent with the following configuration:
110 KiB/sA torrent downloading continuously at approximately
10 MiB/sshould clearly count toward the active-download limit, but another queued torrent is nevertheless started.Related downstream reports:
No equivalent current libtorrent issue appears to exist.
Expected behavior
With:
the behavior should be:
active_downloads.active_downloadsagain.A torrent downloading at several MiB/s should never remain exempt from
active_downloads.Actual behavior
Torrent A may be downloading at approximately
10 MiB/s, while Torrent B is also started despite:In some cases, many or all queued torrents may start.
Steps to reproduce
inactive_down_rate, for example10 MiB/s.Suspected cause
The qBittorrent side appears to pass the configured threshold to libtorrent correctly. For example, a configured value of
10 KiB/sis passed as approximately10,240 bytes/s.The likely issue is libtorrent’s cached inactive state,
m_inactive, and how it interacts with auto-management.The auto-manager exempts torrents for which
torrent::is_inactive()is true from theactive_downloadsandactive_seedslimits. This is expected while a torrent is genuinely inactive.However, the inactive state appears to be debounced for both state transitions:
Using the inactivity interval for the first transition makes sense: a short transfer-rate dip should not immediately free an active slot.
Using the same delay for the reverse transition is problematic. Once an inactive torrent begins transferring above the configured threshold, it can continue to report
is_inactive() == trueuntil the inactivity timer expires.During that interval, the torrent can transfer at a high rate while still being excluded from
active_downloads. The auto-manager may consequently start another queued torrent.There may be a second related issue when
dont_count_slow_torrentsis enabled or its settings are updated. An auto-managed torrent that is paused because it is queued naturally has a payload rate of zero. If such torrents are evaluated as inactive before they have been allowed to run, they may be preclassified as exempt from the active-download limit. The auto-manager can then unpause multiple queued torrents.In other words, the problematic sequence may be:
Suggested fix
1. Clear the inactive state immediately on recovery
The delay should apply when determining that a torrent has become inactive, but not when determining that it has become active again.
Conceptually:
This preserves protection against brief low-rate periods while ensuring that a torrent transferring above the threshold immediately counts against the queue limits.
2. Do not classify queued/paused torrents as inactive based solely on zero rate
A torrent paused by the auto-manager because it is queued has no meaningful transfer rate. Its zero rate should not cause it to be marked inactive before it has been started.
Possible approaches include:
or restricting inactivity accounting to torrents that are:
The exact condition may need to distinguish a user-paused torrent from one paused by auto-management.
3. Re-run auto-management when inactivity is cleared
When
m_inactivechanges from true to false, auto-management should be triggered promptly so thatactive_downloadsis enforced again.Otherwise, even after the state is corrected, too many downloads may remain active until some unrelated event causes another auto-management pass.
Suggested regression tests
Recovered torrent counts immediately
active_downloads = 1.dont_count_slow_torrents.inactive_down_rate.High-rate torrent never frees its slot
active_downloads = 1.inactive_down_rate.auto_manage_startup.Queued torrents are not preclassified inactive
active_downloads = 1.dont_count_slow_torrents.Brief rate dip does not free a slot
auto_manage_startup.Additional diagnostic suggestion
It may help to log the following during an auto-management pass:
That should confirm whether the high-rate torrent is still carrying a stale inactive flag when the additional torrent is started.
Environment
Observed through qBittorrent 5.1.x using libtorrent 2.0.x.
The exact libtorrent version can be added from qBittorrent’s:
Notes
The source-level cause described above is a hypothesis based on the inactivity and auto-management paths. A minimal libtorrent-only reproduction or temporary logging of
m_inactivetransitions would be useful to confirm it.