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) {
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)
}
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(