Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Atomic String Swap panics if created with empty string #126

Closed
KromDaniel opened this issue Jan 8, 2023 · 1 comment · Fixed by #130
Closed

Atomic String Swap panics if created with empty string #126

KromDaniel opened this issue Jan 8, 2023 · 1 comment · Fixed by #130

Comments

@KromDaniel
Copy link

KromDaniel commented Jan 8, 2023

Hey,

I've encountered the following issue with atomic.String

atomicStr := atomic.NewString("")
atomicStr.Swap("string")

error

panic: interface conversion: interface {} is nil, not string [recovered]
	panic: interface conversion: interface {} is nil, not string
	
go.uber.org/atomic.(*String).Swap(...)
	/Users/dkrom/Dev/gonzo/pkg/mod/go.uber.org/atomic@v1.10.0/string.go:64

I guess its because NewString condition

func NewString(val string) *String {
	x := &String{}
	if val != _zeroString {
		x.Store(val)
	}
	return x
}

I'm not sure if its by design or not?

go version go1.19.4 darwin/arm64
atomic @v1.10.0

Thanks a lot!

@eNV25
Copy link
Contributor

eNV25 commented Feb 3, 2023

Needs fixing in Swap method to match Load.

func (x *{{ .Name }}) Swap(val {{ .Type }}) (old {{ .Type }}) {
{{ if .Pack -}}
return {{ .Unpack }}(x.v.Swap({{ .Pack }}(val)))
{{- else -}}{{- /* assume go.uber.org/atomic.Value */ -}}
return x.v.Swap(val).({{ .Type }})
{{- end }}
}

@eNV25 eNV25 mentioned this issue Feb 4, 2023
4 tasks
sywhang pushed a commit that referenced this issue Feb 6, 2023
* Regenerate code to update copyright end year to 2023

* Test behaviour of default values initialized in different ways

This adds repro tests for #126 and #129

* Fix Swap and CompareAndSwap for Value wrappers

Fixes #126, #129

All atomic types can be used without initialization, e.g., `var v
<AtomicType>`. This works fine for integer types as the initialized
value of 0 matches the default value for the user-facing type.  However,
for Value wrappers, they are initialized to `nil`, which is a value that
can't be set (triggers a panic) so the default value for the user-facing
type is forced to be stored as a different value. This leads to multiple
possible values representing the default user-facing type.

E.g., an `atomic.String` with value `""` may be represented by the
underlying atomic as either `nil`, or `""`. This causes issues when we
don't handle the `nil` value correctly, causing to panics in `Swap` and
incorrectly not swapping values in `CompareAndSwap`.

This change fixes the above issues by:
 * Requiring `pack` and `unpack` function in gen-atomicwrapper as the
   only place we weren't supplying them was for `String`, and the
   branching adds unnecessary complexity, especially with added `nil`
   handling.
 * Extending `CompareAndSwap` for `Value` wrappers to try an additional
   `CompareAndSwap(nil, <new>)` only if the original `CompareAndSwap`
   fails and the old value is the zero value.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants