From bc5d79e1d3af266a6495d7d0850a6dba0e5dabee Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Fri, 6 Nov 2015 00:40:47 +1100 Subject: [PATCH] Make torrent.Reader reads fail when the torrent is closed instead of stalling --- client_test.go | 42 ++++++++++++++++++++++++++++++++++++++++++ reader.go | 9 +++++++++ 2 files changed, 51 insertions(+) diff --git a/client_test.go b/client_test.go index b61d6b1b..80d1535c 100644 --- a/client_test.go +++ b/client_test.go @@ -536,6 +536,48 @@ func TestResponsive(t *testing.T) { assert.EqualValues(t, "d\n", string(b)) } +func TestTorrentDroppedDuringResponsiveRead(t *testing.T) { + seederDataDir, mi := testutil.GreetingTestTorrent() + defer os.RemoveAll(seederDataDir) + cfg := TestingConfig + cfg.Seed = true + cfg.DataDir = seederDataDir + seeder, err := NewClient(&cfg) + require.Nil(t, err) + defer seeder.Close() + seeder.AddTorrentSpec(TorrentSpecFromMetaInfo(mi)) + leecherDataDir, err := ioutil.TempDir("", "") + require.Nil(t, err) + defer os.RemoveAll(leecherDataDir) + cfg = TestingConfig + cfg.DataDir = leecherDataDir + leecher, err := NewClient(&cfg) + require.Nil(t, err) + defer leecher.Close() + leecherTorrent, _, _ := leecher.AddTorrentSpec(func() (ret *TorrentSpec) { + ret = TorrentSpecFromMetaInfo(mi) + ret.ChunkSize = 2 + return + }()) + leecherTorrent.AddPeers([]Peer{ + Peer{ + IP: missinggo.AddrIP(seeder.ListenAddr()), + Port: missinggo.AddrPort(seeder.ListenAddr()), + }, + }) + reader := leecherTorrent.NewReader() + reader.SetReadahead(0) + reader.SetResponsive() + b := make([]byte, 2) + _, err = reader.ReadAt(b, 3) + assert.Nil(t, err) + assert.EqualValues(t, "lo", string(b)) + go leecherTorrent.Drop() + n, err := reader.ReadAt(b, 11) + assert.EqualError(t, err, "torrent closed") + assert.EqualValues(t, 0, n) +} + func TestDHTInheritBlocklist(t *testing.T) { ipl := iplist.New(nil) require.NotNil(t, ipl) diff --git a/reader.go b/reader.go index e9f130ed..e26dfe1d 100644 --- a/reader.go +++ b/reader.go @@ -42,6 +42,9 @@ func (r *Reader) readable(off int64) (ret bool) { // defer func() { // log.Println("readable", ret) // }() + if r.t.isClosed() { + return true + } req, ok := r.t.offsetRequest(off) if !ok { panic(off) @@ -138,6 +141,12 @@ again: err = nil return } + if r.t.isClosed() { + if err == nil { + err = errors.New("torrent closed") + } + return + } if err == io.ErrUnexpectedEOF { goto again } -- 2.48.1