httpdl: fix progress-reporter race on name/out; harden mirror & resume validation
Findings from a Rob-Pike-lens review (bugs/races/network), each verified against the code before fixing: - httpdl: name/out are now atomic.Pointer[string] -- the engine publishes a download to the reporter before Run resolves the name, so Stat raced the write (bt already did this) - httpdl: a malformed --proxy fails loudly instead of silently bypassing it - httpdl: a 206 must carry a matching Content-Range; a 200 in segmented mode is fatal so it fails over instead of burning the retry budget - httpdl: single-stream mirror failover validates the range before appending; ErrTooSlow only when the error is a real ctx cancellation - httpdl: idle guard tracks progress by timestamp (no Reset/Stop race, no sticky fired flag) - httpdl/control: reject a resume file whose segments don't tile [0,total) - bt: clamp the listen-port range; verify on-disk data before choosing pieces under --check-integrity - cli: reject size overflow; show --seed-time=MIN; clamp --select-file range - progress/engine/main: clamp ETA against int64 overflow; show queued downloads as waiting; join the reporter on exit instead of a 20ms sleep
This commit is contained in:
22
bt/bt.go
22
bt/bt.go
@@ -68,10 +68,17 @@ func ParsePorts(spec string) []int {
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
// Clamp to the valid port space before iterating: a parseable but oversized
|
||||
// spec like "1-9999999999" would otherwise spin for ~10^10 iterations and
|
||||
// hang startup, even though only [1,65535] can ever be appended.
|
||||
if a < 1 {
|
||||
a = 1
|
||||
}
|
||||
if b > 65535 {
|
||||
b = 65535
|
||||
}
|
||||
for i := a; i <= b; i++ {
|
||||
if i >= 1 && i <= 65535 {
|
||||
ports = append(ports, i)
|
||||
}
|
||||
ports = append(ports, i)
|
||||
}
|
||||
}
|
||||
return ports
|
||||
@@ -306,14 +313,17 @@ func (d *Download) Run(ctx context.Context) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := d.choose(t); err != nil {
|
||||
return err
|
||||
}
|
||||
// --check-integrity: re-hash the existing on-disk data BEFORE arming the
|
||||
// request loop, so already-good pieces are not re-requested from peers (aria2
|
||||
// verifies first, then fetches only what is missing).
|
||||
if d.opts.CheckIntegrity {
|
||||
if err := t.VerifyDataContext(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := d.choose(t); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := d.wait(ctx, t); err != nil {
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user