Skip to content

fix: lock clock sequence in NewV6WithTime#219

Open
vsaraikin wants to merge 1 commit into
google:masterfrom
vsaraikin:fix/newv6withtime-race
Open

fix: lock clock sequence in NewV6WithTime#219
vsaraikin wants to merge 1 commit into
google:masterfrom
vsaraikin:fix/newv6withtime-race

Conversation

@vsaraikin

Copy link
Copy Markdown

Bug

NewV6WithTime generates duplicate UUIDs under concurrency, and has a data race on the shared clock-sequence state.

getTime reads and mutates the package globals lasttime and clockSeq (it bumps clockSeq whenever time hasn't advanced, which is what keeps same-timestamp UUIDs unique). That state is guarded by timeMu: GetTime — used by NewV6() and NewUUID() — takes the lock before calling getTime. NewV6WithTime (added in #172) is the only path that calls getTime directly, without the lock.

So concurrent NewV6WithTime callers read the same clockSeq/lasttime unsynchronized, producing identical UUIDs, and also race with NewV6()/NewUUID(), corrupting their uniqueness state.

Fix

Take timeMu around the getTime call, matching GetTime:

func NewV6WithTime(customTime *time.Time) (UUID, error) {
	timeMu.Lock()
	now, seq, err := getTime(customTime)
	timeMu.Unlock()
	...

Testing

Added TestNewV6WithTimeConcurrentUnique: 8 goroutines generate 2000 V6 UUIDs each from the same fixed timestamp (16000 < 16384 clock-sequence values, so all must be unique). On the current code it fails deterministically (hundreds of duplicates) and -race reports the data race on lasttime/clockSeq; with the fix it passes cleanly. The full suite passes under -race, and gofmt -s is clean.

NewV6WithTime called getTime directly, bypassing timeMu, while every other
caller (GetTime, used by NewV6/NewUUID) holds it. getTime reads and mutates
the shared lasttime/clockSeq state, so concurrent NewV6WithTime calls raced
and produced duplicate UUIDs. Take timeMu around getTime.
@vsaraikin
vsaraikin requested a review from a team as a code owner July 12, 2026 11:58
@google-cla

google-cla Bot commented Jul 12, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

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 this pull request may close these issues.

1 participant