diff --git a/reader.go b/reader.go index 1f68fdbe..1e1c36e1 100644 --- a/reader.go +++ b/reader.go @@ -199,6 +199,10 @@ func (r *reader) waitAvailable(pos, wanted int64, ctxErr *error, wait bool) (ava err = *ctxErr return } + if r.t.dataDownloadDisallowed || !r.t.networkingEnabled { + err = errors.New("downloading disabled and data not already available") + return + } if !wait { return } diff --git a/test/issue377_test.go b/test/issue377_test.go index abc57a90..05ef1429 100644 --- a/test/issue377_test.go +++ b/test/issue377_test.go @@ -2,6 +2,8 @@ package test import ( "errors" + "io" + "io/ioutil" "os" "sync" "testing" @@ -73,7 +75,27 @@ func testReceiveChunkStorageFailure(t *testing.T, seederFast bool) { // Tell the seeder to find the leecher. Is it guaranteed seeders will always try to do this? seederTorrent.AddClientPeer(leecherClient) <-leecherTorrent.GotInfo() - assertReadAllGreeting(t, leecherTorrent.NewReader()) + r := leecherTorrent.Files()[0].NewReader() + defer r.Close() + // We can't use assertReadAllGreeting here, because the default storage write error handler + // disables data downloads, which now causes Readers to error when they're blocked. + if false { + assertReadAllGreeting(t, leecherTorrent.NewReader()) + } else { + for func() bool { + // We don't seem to need to seek, but that's probably just because the storage failure is + // happening on the first read. + r.Seek(0, io.SeekStart) + output, err := ioutil.ReadAll(r) + if err != nil { + t.Logf("got error while reading: %v", err) + return true + } + assert.EqualValues(t, testutil.GreetingFileContents, output) + return false + }() { + } + } // TODO: Check that PeerConns fastEnabled matches seederFast? //select {} } diff --git a/torrent.go b/torrent.go index ace386eb..561d3d60 100644 --- a/torrent.go +++ b/torrent.go @@ -2024,6 +2024,7 @@ func (t *Torrent) onWriteChunkErr(err error) { go t.userOnWriteChunkErr(err) return } + t.logger.WithDefaultLevel(log.Critical).Printf("default chunk write error handler: disabling data download") t.disallowDataDownloadLocked() } @@ -2038,12 +2039,14 @@ func (t *Torrent) disallowDataDownloadLocked() { t.iterPeers(func(c *peer) { c.updateRequests() }) + t.tickleReaders() } func (t *Torrent) AllowDataDownload() { t.cl.lock() defer t.cl.unlock() t.dataDownloadDisallowed = false + t.tickleReaders() t.iterPeers(func(c *peer) { c.updateRequests() })