Description
If there are multiple goroutines calling namespace.WithNamespace on a ctx that already had namespace, there will be a data race like:
WARNING: DATA RACE
Write at 0x00c00041a8c8 by goroutine 84:
github.com/containerd/containerd/vendor/github.com/containerd/ttrpc.MD.Set()
go/src/github.com/containerd/containerd/vendor/github.com/containerd/ttrpc/metadata.go:48 +0x1be
github.com/containerd/containerd/namespaces.withTTRPCNamespaceHeader()
go/src/github.com/containerd/containerd/namespaces/ttrpc.go:35 +0x1f2
github.com/containerd/containerd/namespaces.WithNamespace()
go/src/github.com/containerd/containerd/namespaces/context.go:41 +0x209
Maybe this is because withTTRPCNamespaceHeader sets the MD directly,
|
func withTTRPCNamespaceHeader(ctx context.Context, namespace string) context.Context { |
|
md, ok := ttrpc.GetMetadata(ctx) |
|
if !ok { |
|
md = ttrpc.MD{} |
|
} |
|
md.Set(TTRPCHeader, namespace) |
while
withGRPCNamespaceHeader will take a copy of MD.
|
func withGRPCNamespaceHeader(ctx context.Context, namespace string) context.Context { |
|
// also store on the grpc headers so it gets picked up by any clients that |
|
// are using this. |
|
nsheader := metadata.Pairs(GRPCHeader, namespace) |
|
md, ok := metadata.FromOutgoingContext(ctx) // merge with outgoing context. |
|
if !ok { |
|
md = nsheader |
|
} else { |
|
// order ensures the latest is first in this list. |
|
md = metadata.Join(nsheader, md) |
So is it ok here? Or should we add metadata copy functions to ttrpc and use them in withTTRPCNamespaceHeader ?
Description
If there are multiple goroutines calling
namespace.WithNamespaceon a ctx that already had namespace, there will be a data race like:Maybe this is because
withTTRPCNamespaceHeadersets the MD directly,containerd/namespaces/ttrpc.go
Lines 30 to 35 in 0b7abc0
while
withGRPCNamespaceHeaderwill take a copy of MD.containerd/namespaces/grpc.go
Lines 32 to 41 in bbe14f0
So is it ok here? Or should we add metadata copy functions to ttrpc and use them in
withTTRPCNamespaceHeader?