connection.go | 16 +++++++++++----- diff --git a/connection.go b/connection.go index b87562157eca88fee3ffc406919c68f53f26f74e..7d94f08b95aa9c6b95f5dcfe65c48b9f72db9c41 100644 --- a/connection.go +++ b/connection.go @@ -1061,11 +1061,17 @@ for c := range t.conns { c.postCancel(req) } - cl.mu.Unlock() - // Write the chunk out. Note that the upper bound on chunk writing - // concurrency will be the number of connections. - err := t.writeChunk(int(msg.Index), int64(msg.Begin), msg.Piece) - cl.mu.Lock() + err := func() error { + cl.mu.Unlock() + defer cl.mu.Lock() + // Write the chunk out. Note that the upper bound on chunk writing + // concurrency will be the number of connections. We write inline with + // receiving the chunk (with this lock dance), because we want to + // handle errors synchronously and I haven't thought of a nice way to + // defer any concurrency to the storage and have that notify the + // client of errors. TODO: Do that instead. + return t.writeChunk(int(msg.Index), int64(msg.Begin), msg.Piece) + }() piece.decrementPendingWrites()