From 24ff1bbf75794c69362555805d3580e53c324865 Mon Sep 17 00:00:00 2001 From: 1911860538 Date: Fri, 15 Aug 2025 20:55:31 +0800 Subject: [PATCH 1/3] net: prevent defer misuse in for loops --- src/net/dial.go | 61 ++++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/src/net/dial.go b/src/net/dial.go index a87c57603a813c..4b99d4c18401bc 100644 --- a/src/net/dial.go +++ b/src/net/dial.go @@ -727,38 +727,13 @@ func (sd *sysDialer) dialParallel(ctx context.Context, primaries, fallbacks addr // dialSerial connects to a list of addresses in sequence, returning // either the first successful connection, or the first error. func (sd *sysDialer) dialSerial(ctx context.Context, ras addrList) (Conn, error) { + var conn Conn var firstErr error // The error from the first address is most relevant. - for i, ra := range ras { - select { - case <-ctx.Done(): - return nil, &OpError{Op: "dial", Net: sd.network, Source: sd.LocalAddr, Addr: ra, Err: mapErr(ctx.Err())} - default: - } - - dialCtx := ctx - if deadline, hasDeadline := ctx.Deadline(); hasDeadline { - partialDeadline, err := partialDeadline(time.Now(), deadline, len(ras)-i) - if err != nil { - // Ran out of time. - if firstErr == nil { - firstErr = &OpError{Op: "dial", Net: sd.network, Source: sd.LocalAddr, Addr: ra, Err: err} - } - break - } - if partialDeadline.Before(deadline) { - var cancel context.CancelFunc - dialCtx, cancel = context.WithDeadline(ctx, partialDeadline) - defer cancel() - } - } - - c, err := sd.dialSingle(dialCtx, ra) - if err == nil { - return c, nil - } + for i := range ras { + conn, firstErr = sd.dialAddr(ctx, ras, i) if firstErr == nil { - firstErr = err + return conn, nil } } @@ -768,6 +743,34 @@ func (sd *sysDialer) dialSerial(ctx context.Context, ras addrList) (Conn, error) return nil, firstErr } +// dialAddr connects to an address, +// returning either a successful connection, or an error. +func (sd *sysDialer) dialAddr(ctx context.Context, ras addrList, i int) (Conn, error) { + ra := ras[i] + + select { + case <-ctx.Done(): + return nil, &OpError{Op: "dial", Net: sd.network, Source: sd.LocalAddr, Addr: ra, Err: mapErr(ctx.Err())} + default: + } + + dialCtx := ctx + if deadline, hasDeadline := ctx.Deadline(); hasDeadline { + partialDeadline, err := partialDeadline(time.Now(), deadline, len(ras)-i) + if err != nil { + // Ran out of time. + return nil, &OpError{Op: "dial", Net: sd.network, Source: sd.LocalAddr, Addr: ra, Err: err} + } + if partialDeadline.Before(deadline) { + var cancel context.CancelFunc + dialCtx, cancel = context.WithDeadline(ctx, partialDeadline) + defer cancel() + } + } + + return sd.dialSingle(dialCtx, ra) +} + // dialSingle attempts to establish and returns a single connection to // the destination address. func (sd *sysDialer) dialSingle(ctx context.Context, ra Addr) (c Conn, err error) { From 05bd55ec513d6e7fdd0beb454867bd061c71600f Mon Sep 17 00:00:00 2001 From: 1911860538 Date: Fri, 15 Aug 2025 21:50:39 +0800 Subject: [PATCH 2/3] net: fix dialSerial returns a non-first error --- src/net/dial.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/net/dial.go b/src/net/dial.go index 4b99d4c18401bc..ae1d5ef51e64a3 100644 --- a/src/net/dial.go +++ b/src/net/dial.go @@ -727,14 +727,16 @@ func (sd *sysDialer) dialParallel(ctx context.Context, primaries, fallbacks addr // dialSerial connects to a list of addresses in sequence, returning // either the first successful connection, or the first error. func (sd *sysDialer) dialSerial(ctx context.Context, ras addrList) (Conn, error) { - var conn Conn var firstErr error // The error from the first address is most relevant. for i := range ras { - conn, firstErr = sd.dialAddr(ctx, ras, i) - if firstErr == nil { + conn, err := sd.dialAddr(ctx, ras, i) + if err == nil { return conn, nil } + if firstErr == nil { + firstErr = err + } } if firstErr == nil { From 3a40c12fab3cb54dc8f7b43d4f28752bd1a6c368 Mon Sep 17 00:00:00 2001 From: 1911860538 Date: Wed, 27 Aug 2025 23:06:57 +0800 Subject: [PATCH 3/3] net: avoid creating dialAddr for defer in for loops --- src/net/dial.go | 60 ++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/src/net/dial.go b/src/net/dial.go index ae1d5ef51e64a3..70e27193dd22ab 100644 --- a/src/net/dial.go +++ b/src/net/dial.go @@ -729,10 +729,36 @@ func (sd *sysDialer) dialParallel(ctx context.Context, primaries, fallbacks addr func (sd *sysDialer) dialSerial(ctx context.Context, ras addrList) (Conn, error) { var firstErr error // The error from the first address is most relevant. - for i := range ras { - conn, err := sd.dialAddr(ctx, ras, i) + for i, ra := range ras { + select { + case <-ctx.Done(): + return nil, &OpError{Op: "dial", Net: sd.network, Source: sd.LocalAddr, Addr: ra, Err: mapErr(ctx.Err())} + default: + } + + dialCtx := ctx + var cancel context.CancelFunc + + if deadline, hasDeadline := ctx.Deadline(); hasDeadline { + partialDeadline, err := partialDeadline(time.Now(), deadline, len(ras)-i) + if err != nil { + // Ran out of time. + if firstErr == nil { + firstErr = &OpError{Op: "dial", Net: sd.network, Source: sd.LocalAddr, Addr: ra, Err: err} + } + break + } + if partialDeadline.Before(deadline) { + dialCtx, cancel = context.WithDeadline(ctx, partialDeadline) + } + } + + c, err := sd.dialSingle(dialCtx, ra) + if cancel != nil { + cancel() + } if err == nil { - return conn, nil + return c, nil } if firstErr == nil { firstErr = err @@ -745,34 +771,6 @@ func (sd *sysDialer) dialSerial(ctx context.Context, ras addrList) (Conn, error) return nil, firstErr } -// dialAddr connects to an address, -// returning either a successful connection, or an error. -func (sd *sysDialer) dialAddr(ctx context.Context, ras addrList, i int) (Conn, error) { - ra := ras[i] - - select { - case <-ctx.Done(): - return nil, &OpError{Op: "dial", Net: sd.network, Source: sd.LocalAddr, Addr: ra, Err: mapErr(ctx.Err())} - default: - } - - dialCtx := ctx - if deadline, hasDeadline := ctx.Deadline(); hasDeadline { - partialDeadline, err := partialDeadline(time.Now(), deadline, len(ras)-i) - if err != nil { - // Ran out of time. - return nil, &OpError{Op: "dial", Net: sd.network, Source: sd.LocalAddr, Addr: ra, Err: err} - } - if partialDeadline.Before(deadline) { - var cancel context.CancelFunc - dialCtx, cancel = context.WithDeadline(ctx, partialDeadline) - defer cancel() - } - } - - return sd.dialSingle(dialCtx, ra) -} - // dialSingle attempts to establish and returns a single connection to // the destination address. func (sd *sysDialer) dialSingle(ctx context.Context, ra Addr) (c Conn, err error) {