Repository navigation
fix: synchronize DefaultEntropy reads - #138
perfloop[bot] wants to merge 3 commits into
Conversation
Signed-off-by: Perfloop Agent <agent@perfloop.ai>
Signed-off-by: Perfloop Agent <agent@perfloop.ai>
|
Thanks for the spot on the race. I think a simpler fix is to just add a pointer-receiver Read method to LockedMonotonicReader itself, and leave defaultEntropy as it is: // Read synchronizes calls to the wrapped MonotonicReader.
func (r *LockedMonotonicReader) Read(p []byte) (int, error) {
r.mu.Lock()
defer r.mu.Unlock()
return r.MonotonicReader.Read(p)
}(That also fixes LockedMonotonicReaders that callers construct themselves, not just the default one.) It seems the reason this PR doesn’t take that approach is because it’s trying to preserve the property that a LockedMonotonicReader value implements io.Reader. But AFAICT there’s no reason to do that, as it’s not valid in the first place:
So the only code that would break is code that’s already silently broken. wdyt? |
|
Response to this feedback. Agreed. I’ll add |
Signed-off-by: Perfloop Agent <agent@perfloop.ai>
|
Addressed in Added a pointer-receiver |
|
I believe this is ready @peterbourgon |
@peterbourgon @tsenart
DefaultEntropyreturns anio.Readerwhose dynamic value is*LockedMonotonicReader, but the promotedReadpath bypassed the mutex used byMonotonicRead. A pointer-receiverReadnow takes the same mutex and forwards the inner reader's bytes, count, and error unchanged. This also synchronizes callers who constructLockedMonotonicReaderthemselves.Newstill sees the default reader as aMonotonicReader, soMakekeeps its monotonic-generation path. The pointer form satisfiesio.Reader; the value form no longer does. A copied value cannot share the mutex and does not implementMonotonicReader, so use the pointer form.TestDefaultEntropyConcurrentReadAndMakeexercises the public default operations under the race detector.TestLockedMonotonicReaderConcurrentReadAndNewcovers a caller-constructed wrapper.TestLockedMonotonicReaderReadchecks byte and error passthrough, andTestDefaultEntropyMonotonicReaderprotects dispatch.BenchmarkDefaultEntropyReadinulid_test.gomeasures serial public reads. The separate race-comparison harness is not part of this pull request.This condition holds with this change and does not hold at
75921a7395850ea47ed4dfd832184a5a294c8fde:Concurrent calls to Make and Read on the reader returned by DefaultEntropy do not race on the wrapped entropy state, assuming the wrapped reader is accessed only through LockedMonotonicReader and is not concurrently replaced..The Unreleased changelog records the fix. On Linux, all packages built, and formatting, vet, static analysis, the race-enabled test suite, and the native benchmark passed. The macOS and Windows race-test matrix jobs did not run here because this environment is Linux-only; those jobs remain target-CI work.
Generated by Perfloop.