Skip to content

Commit 06a7052

Browse files
Ensure that editing fetched Attributes is race-free in any case.
Signed-off-by: Andreas Bergmeier <[email protected]>
1 parent e6a74ef commit 06a7052

File tree

1 file changed

+23
-1
lines changed

1 file changed

+23
-1
lines changed

protocol/pubsub/v2/attributes.go

+23-1
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,34 @@ import (
1414
type withCustomAttributes struct{}
1515

1616
func AttributesFrom(ctx context.Context) map[string]string {
17-
return binding.GetOrDefaultFromCtx(ctx, withCustomAttributes{}, make(map[string]string)).(map[string]string)
17+
ctxVal := binding.GetOrDefaultFromCtx(ctx, withCustomAttributes{}, nil)
18+
if ctxVal == nil {
19+
return make(map[string]string, 0)
20+
}
21+
22+
m := ctxVal.(map[string]string)
23+
24+
// Since it is possible that we get the same map from one ctx multiple times
25+
// we need to make sure, that it is race-free to modify returned map.
26+
cp := make(map[string]string, len(m))
27+
for k, v := range m {
28+
cp[k] = v
29+
}
30+
return cp
1831
}
1932

2033
// WithCustomAttributes sets Message Attributes without any CloudEvent logic.
2134
// Note that this function is not intended for CloudEvent Extensions or any `ce-`-prefixed Attributes.
2235
// For these please see `Event` and `Event.SetExtension`.
2336
func WithCustomAttributes(ctx context.Context, attrs map[string]string) context.Context {
37+
if attrs != nil {
38+
// Since it is likely that the map gets used in another goroutine
39+
// ensure that modifying passed in map is race-free.
40+
cp := make(map[string]string, len(attrs))
41+
for k, v := range attrs {
42+
cp[k] = v
43+
}
44+
attrs = cp
45+
}
2446
return context.WithValue(ctx, withCustomAttributes{}, attrs)
2547
}

0 commit comments

Comments
 (0)