]> Sergey Matveev's repositories - btrtrc.git/commitdiff
cmd/torrent download: Propagate write errors
authorMatt Joiner <anacrolix@gmail.com>
Wed, 28 Feb 2024 04:47:31 +0000 (15:47 +1100)
committerMatt Joiner <anacrolix@gmail.com>
Wed, 28 Feb 2024 04:47:31 +0000 (15:47 +1100)
cmd/torrent/download.go

index 065ea2ad02e37ca7bd86a1c4c5ba2d020ee627e8..1fc4759f99f357cf9f5df69de14624bc9aa92bac 100644 (file)
@@ -89,7 +89,13 @@ func resolveTestPeers(addrs []string) (ret []torrent.PeerInfo) {
        return
 }
 
-func addTorrents(ctx context.Context, client *torrent.Client, flags downloadFlags, wg *sync.WaitGroup) error {
+func addTorrents(
+       ctx context.Context,
+       client *torrent.Client,
+       flags downloadFlags,
+       wg *sync.WaitGroup,
+       fatalErr func(err error),
+) error {
        testPeers := resolveTestPeers(flags.TestPeer)
        for _, arg := range flags.Torrent {
                t, err := func() (*torrent.Torrent, error) {
@@ -133,6 +139,10 @@ func addTorrents(ctx context.Context, client *torrent.Client, flags downloadFlag
                if err != nil {
                        return fmt.Errorf("adding torrent for %q: %w", arg, err)
                }
+               t.SetOnWriteChunkError(func(err error) {
+                       err = fmt.Errorf("error writing chunk for %v: %w", t, err)
+                       fatalErr(err)
+               })
                if flags.Progress {
                        torrentBar(t, flags.PieceStates)
                }
@@ -344,17 +354,33 @@ func downloadErr(flags downloadFlags) error {
                client.WriteStatus(w)
        })
        var wg sync.WaitGroup
-       err = addTorrents(ctx, client, flags, &wg)
+       fatalErr := make(chan error, 1)
+       err = addTorrents(ctx, client, flags, &wg,
+               func(err error) {
+                       select {
+                       case fatalErr <- err:
+                       default:
+                               panic(err)
+                       }
+               })
        if err != nil {
                return fmt.Errorf("adding torrents: %w", err)
        }
        started := time.Now()
        defer outputStats(client, flags)
-       wg.Wait()
-       if ctx.Err() == nil {
-               log.Print("downloaded ALL the torrents")
-       } else {
-               err = ctx.Err()
+       wgWaited := make(chan struct{})
+       go func() {
+               defer close(wgWaited)
+               wg.Wait()
+       }()
+       select {
+       case <-wgWaited:
+               if ctx.Err() == nil {
+                       log.Print("downloaded ALL the torrents")
+               } else {
+                       err = ctx.Err()
+               }
+       case err = <-fatalErr:
        }
        clientConnStats := client.ConnStats()
        log.Printf(