alanmcgovern / monotorrent

The official repository for MonoTorrent, a bittorrent library for .NET

Home Page:https://github.com/alanmcgovern/monotorrent

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Client locks up and never starts downloading if it has nothing to download at start

ManlyMarco opened this issue · comments

It looks like if the torrent has nothing to download for some time after it is started, it will lock up and never start downloading. It does connect to my seed for that torrent and keeps the connection active, but never actually downloads anything.

It doesn't matter if any files are finished and the torrent is seeding, or if nothing is downloaded yet. As long as there are no transfers for some time after starting, it just permanently dies.

I have 1 seed for the torrent (also using MonoTorrent) that is verified to work fine with qBittorrent. I can see on the seed that the client does in fact correctly connect to it but it never asks for any chunks.

How to reproduce:
The torrent needs a singular seed with an open port. It seems like the key is that the client has nothing to do and falls asleep forever.

// There is some unnecessry code but since the issue seems to be timing-dependant 
// and somewhat random I kept it all from when the issue seemed to be the most reliably reproduced
var t = await _source.Client.AddAsync(torrent, "e:\\test", new TorrentSettingsBuilder()
{
    CreateContainingDirectory = false,
    AllowInitialSeeding = true
}.ToSettings());

await t.WaitForMetadataAsync(cancellationToken);

// Not sure if necessary or not, probably not
await t.HashCheckAsync(false);

foreach (var f in t.Files)
{
    // Stop the torrent from downloading after starting. If some files are finished they can be left enabled.
    await t.SetFilePriorityAsync(f, Priority.DoNotDownload);
    // Not sure if necessary or not, probably not
    await t.MoveFileAsync(f, Path.Combine("e:\\test2", Path.GetRandomFileName()));
}

await t.StartAsync(); 

// This line causes the torrent to never start downloading from the seeder
await Task.Delay(20000);

foreach (var f in t.Files)
{
    // This should make the client start downloading
    await t.SetFilePriorityAsync(f, Priority.High);
}

// Adding these two "fixes" the issue but is not very practical
//await t.StopAsync();
//await t.StartAsync();

while (!t.Complete)
{
    await Task.Delay(1000);
    Console.WriteLine($"State={t.State} Progress={t.Progress} Seeds={t.Peers.Seeds}");
}

Confirmed on latest stable and on 3.0.0-beta.rev0106 releases.

That should be fixed now! This looks like an oversight. The original intent was to update the 'AmInterested' state of remote peers on an as-needed basis. Back in the day there were a limited number of ways the state could change, primarily when a message is sent/received: HaveAll/HaveNone/Have messages.

However, the engine got a little more advanced and there are some dynamic ways the status can change, i.e. files which were marked as DoNotDownload are now marked as Normal priority, or files which were pending a hashcheck have now been background hashed, or the v2 info hashes have now been received so some pieces can now be requested.

It's a bit harder to enumerate all possible cases now, so I just added a timed refresh. This kind of timed refresh is already performed to disconnect peers who are non-responsive so there was a convenient place for it.

Thanks for reporting!