-
Notifications
You must be signed in to change notification settings - Fork 645
consensus: rename (*PeerState).ToJSON to MarshalJSON (backport #524) #532
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
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
In (*PeerState).PickSendVote, there is a Debug-level log that includes the PeerState value as a logging field. By default, zerolog json-encodes a struct passed as a log field (when the struct doesn't implement zerolog.LogObjectMarshaler). Because PeerState didn't have a MarshalJSON method, the JSON encoder fell back to reflection to encode the PeerState value. Reflection did not acquire the lock, and there were data races resulting from an unsynchronized read while logging the PeerState, and concurrent (locked) writes at least during (*PeerState).SetHasProposal and (*PeerState).SetHasVote. Given that there was only one call to (*PeerState).ToJSON in the cometbft repo, it seemed appropriate to just rename ToJSON to MarshalJSON, as opposed to leaving ToJSON for backwards compatibility. Any third party calls to ToJSON should be able to easily change the method being called. Example data race (which is no longer reproducible with this change): ``` ================== WARNING: DATA RACE Read at 0x00c0004a4870 by goroutine 131: reflect.Value.Bool() /opt/homebrew/Cellar/go/1.20.1/libexec/src/reflect/value.go:288 +0x7c encoding/json.boolEncoder() /opt/homebrew/Cellar/go/1.20.1/libexec/src/encoding/json/encode.go:539 +0x88 encoding/json.structEncoder.encode() /opt/homebrew/Cellar/go/1.20.1/libexec/src/encoding/json/encode.go:759 +0x1bc encoding/json.structEncoder.encode-fm() <autogenerated>:1 +0x94 encoding/json.structEncoder.encode() /opt/homebrew/Cellar/go/1.20.1/libexec/src/encoding/json/encode.go:759 +0x1bc encoding/json.structEncoder.encode-fm() <autogenerated>:1 +0x94 encoding/json.ptrEncoder.encode() /opt/homebrew/Cellar/go/1.20.1/libexec/src/encoding/json/encode.go:943 +0x2a4 encoding/json.ptrEncoder.encode-fm() <autogenerated>:1 +0x6c encoding/json.(*encodeState).reflectValue() /opt/homebrew/Cellar/go/1.20.1/libexec/src/encoding/json/encode.go:358 +0x74 encoding/json.(*encodeState).marshal() /opt/homebrew/Cellar/go/1.20.1/libexec/src/encoding/json/encode.go:330 +0x1a0 encoding/json.Marshal() /opt/homebrew/Cellar/go/1.20.1/libexec/src/encoding/json/encode.go:161 +0xa0 github.com/rs/zerolog.init.1.func1() /Users/hh/go/pkg/mod/github.com/rs/zerolog@v1.29.0/encoder_json.go:21 +0x4c github.com/rs/zerolog/internal/json.Encoder.AppendInterface() /Users/hh/go/pkg/mod/github.com/rs/zerolog@v1.29.0/internal/json/types.go:366 +0x5c github.com/rs/zerolog.appendFieldList() /Users/hh/go/pkg/mod/github.com/rs/zerolog@v1.29.0/fields.go:273 +0x2b8c github.com/rs/zerolog.appendFields() /Users/hh/go/pkg/mod/github.com/rs/zerolog@v1.29.0/fields.go:21 +0x160 github.com/rs/zerolog.(*Event).Fields() /Users/hh/go/pkg/mod/github.com/rs/zerolog@v1.29.0/event.go:165 +0x90 cosmossdk.io/log.zeroLogWrapper.Debug() /Users/hh/go/pkg/mod/cosmossdk.io/log@v0.0.0-20230313123454-0fe816b71a62/logger.go:89 +0x18 github.com/cosmos/cosmos-sdk/server/log.(*CometZeroLogWrapper).Debug() <autogenerated>:1 +0x74 github.com/cometbft/cometbft/consensus.(*PeerState).PickSendVote() /Users/hh/go/src/github.com/cometbft/cometbft/consensus/reactor.go:1138 +0x1bc github.com/cometbft/cometbft/consensus.(*Reactor).gossipVotesForHeight() /Users/hh/go/src/github.com/cometbft/cometbft/consensus/reactor.go:794 +0x260 github.com/cometbft/cometbft/consensus.(*Reactor).gossipVotesRoutine() /Users/hh/go/src/github.com/cometbft/cometbft/consensus/reactor.go:724 +0x2cc github.com/cometbft/cometbft/consensus.(*Reactor).AddPeer.func2() /Users/hh/go/src/github.com/cometbft/cometbft/consensus/reactor.go:199 +0x58 Previous write at 0x00c0004a4870 by goroutine 130: github.com/cometbft/cometbft/consensus.(*PeerState).SetHasProposal() /Users/hh/go/src/github.com/cometbft/cometbft/consensus/reactor.go:1096 +0x118 github.com/cometbft/cometbft/consensus.(*Reactor).gossipDataRoutine() /Users/hh/go/src/github.com/cometbft/cometbft/consensus/reactor.go:617 +0xab8 github.com/cometbft/cometbft/consensus.(*Reactor).AddPeer.func1() /Users/hh/go/src/github.com/cometbft/cometbft/consensus/reactor.go:198 +0x58 Goroutine 131 (running) created at: github.com/cometbft/cometbft/consensus.(*Reactor).AddPeer() /Users/hh/go/src/github.com/cometbft/cometbft/consensus/reactor.go:199 +0x240 github.com/cometbft/cometbft/p2p.(*Switch).addPeer() /Users/hh/go/src/github.com/cometbft/cometbft/p2p/switch.go:855 +0x7b4 github.com/cometbft/cometbft/p2p.(*Switch).acceptRoutine() /Users/hh/go/src/github.com/cometbft/cometbft/p2p/switch.go:707 +0x704 github.com/cometbft/cometbft/p2p.(*Switch).OnStart.func1() /Users/hh/go/src/github.com/cometbft/cometbft/p2p/switch.go:241 +0x34 Goroutine 130 (running) created at: github.com/cometbft/cometbft/consensus.(*Reactor).AddPeer() /Users/hh/go/src/github.com/cometbft/cometbft/consensus/reactor.go:198 +0x164 github.com/cometbft/cometbft/p2p.(*Switch).addPeer() /Users/hh/go/src/github.com/cometbft/cometbft/p2p/switch.go:855 +0x7b4 github.com/cometbft/cometbft/p2p.(*Switch).acceptRoutine() /Users/hh/go/src/github.com/cometbft/cometbft/p2p/switch.go:707 +0x704 github.com/cometbft/cometbft/p2p.(*Switch).OnStart.func1() /Users/hh/go/src/github.com/cometbft/cometbft/p2p/switch.go:241 +0x34 ================== ``` --- #### PR checklist - [ ] Tests written/updated - [x] Changelog entry added in `.changelog` (we use [unclog](https://github.com/informalsystems/unclog) to manage our changelog) - [ ] Updated relevant documentation (`docs/` or `spec/`) and code comments (cherry picked from commit 587bc0b) # Conflicts: # .changelog/v0.37.0/bug-fixes/524-rename-peerstate-tojson.md
cason
approved these changes
Mar 14, 2023
Signed-off-by: Thane Thomson <connect@thanethomson.com>
thanethomson
approved these changes
Mar 15, 2023
mark-rushakoff
added a commit
to cosmos/cosmos-sdk
that referenced
this pull request
Apr 11, 2023
This includes two fixes for two data races that occasionally happen in Cosmos SDK tests: cometbft/cometbft#690 and cometbft/cometbft#532. We will eventually be switching to CometBFT v0.38 (see #15519), which also contains those fixes.
8 tasks
roy-dydx
pushed a commit
to dydxprotocol/cometbft
that referenced
this pull request
Jul 11, 2023
…ft#524) (cometbft#532) * consensus: rename (*PeerState).ToJSON to MarshalJSON (cometbft#524) In (*PeerState).PickSendVote, there is a Debug-level log that includes the PeerState value as a logging field. By default, zerolog json-encodes a struct passed as a log field (when the struct doesn't implement zerolog.LogObjectMarshaler). Because PeerState didn't have a MarshalJSON method, the JSON encoder fell back to reflection to encode the PeerState value. Reflection did not acquire the lock, and there were data races resulting from an unsynchronized read while logging the PeerState, and concurrent (locked) writes at least during (*PeerState).SetHasProposal and (*PeerState).SetHasVote. Given that there was only one call to (*PeerState).ToJSON in the cometbft repo, it seemed appropriate to just rename ToJSON to MarshalJSON, as opposed to leaving ToJSON for backwards compatibility. Any third party calls to ToJSON should be able to easily change the method being called. Example data race (which is no longer reproducible with this change): ``` ================== WARNING: DATA RACE Read at 0x00c0004a4870 by goroutine 131: reflect.Value.Bool() /opt/homebrew/Cellar/go/1.20.1/libexec/src/reflect/value.go:288 +0x7c encoding/json.boolEncoder() /opt/homebrew/Cellar/go/1.20.1/libexec/src/encoding/json/encode.go:539 +0x88 encoding/json.structEncoder.encode() /opt/homebrew/Cellar/go/1.20.1/libexec/src/encoding/json/encode.go:759 +0x1bc encoding/json.structEncoder.encode-fm() <autogenerated>:1 +0x94 encoding/json.structEncoder.encode() /opt/homebrew/Cellar/go/1.20.1/libexec/src/encoding/json/encode.go:759 +0x1bc encoding/json.structEncoder.encode-fm() <autogenerated>:1 +0x94 encoding/json.ptrEncoder.encode() /opt/homebrew/Cellar/go/1.20.1/libexec/src/encoding/json/encode.go:943 +0x2a4 encoding/json.ptrEncoder.encode-fm() <autogenerated>:1 +0x6c encoding/json.(*encodeState).reflectValue() /opt/homebrew/Cellar/go/1.20.1/libexec/src/encoding/json/encode.go:358 +0x74 encoding/json.(*encodeState).marshal() /opt/homebrew/Cellar/go/1.20.1/libexec/src/encoding/json/encode.go:330 +0x1a0 encoding/json.Marshal() /opt/homebrew/Cellar/go/1.20.1/libexec/src/encoding/json/encode.go:161 +0xa0 github.com/rs/zerolog.init.1.func1() /Users/hh/go/pkg/mod/github.com/rs/zerolog@v1.29.0/encoder_json.go:21 +0x4c github.com/rs/zerolog/internal/json.Encoder.AppendInterface() /Users/hh/go/pkg/mod/github.com/rs/zerolog@v1.29.0/internal/json/types.go:366 +0x5c github.com/rs/zerolog.appendFieldList() /Users/hh/go/pkg/mod/github.com/rs/zerolog@v1.29.0/fields.go:273 +0x2b8c github.com/rs/zerolog.appendFields() /Users/hh/go/pkg/mod/github.com/rs/zerolog@v1.29.0/fields.go:21 +0x160 github.com/rs/zerolog.(*Event).Fields() /Users/hh/go/pkg/mod/github.com/rs/zerolog@v1.29.0/event.go:165 +0x90 cosmossdk.io/log.zeroLogWrapper.Debug() /Users/hh/go/pkg/mod/cosmossdk.io/log@v0.0.0-20230313123454-0fe816b71a62/logger.go:89 +0x18 github.com/cosmos/cosmos-sdk/server/log.(*CometZeroLogWrapper).Debug() <autogenerated>:1 +0x74 github.com/cometbft/cometbft/consensus.(*PeerState).PickSendVote() /Users/hh/go/src/github.com/cometbft/cometbft/consensus/reactor.go:1138 +0x1bc github.com/cometbft/cometbft/consensus.(*Reactor).gossipVotesForHeight() /Users/hh/go/src/github.com/cometbft/cometbft/consensus/reactor.go:794 +0x260 github.com/cometbft/cometbft/consensus.(*Reactor).gossipVotesRoutine() /Users/hh/go/src/github.com/cometbft/cometbft/consensus/reactor.go:724 +0x2cc github.com/cometbft/cometbft/consensus.(*Reactor).AddPeer.func2() /Users/hh/go/src/github.com/cometbft/cometbft/consensus/reactor.go:199 +0x58 Previous write at 0x00c0004a4870 by goroutine 130: github.com/cometbft/cometbft/consensus.(*PeerState).SetHasProposal() /Users/hh/go/src/github.com/cometbft/cometbft/consensus/reactor.go:1096 +0x118 github.com/cometbft/cometbft/consensus.(*Reactor).gossipDataRoutine() /Users/hh/go/src/github.com/cometbft/cometbft/consensus/reactor.go:617 +0xab8 github.com/cometbft/cometbft/consensus.(*Reactor).AddPeer.func1() /Users/hh/go/src/github.com/cometbft/cometbft/consensus/reactor.go:198 +0x58 Goroutine 131 (running) created at: github.com/cometbft/cometbft/consensus.(*Reactor).AddPeer() /Users/hh/go/src/github.com/cometbft/cometbft/consensus/reactor.go:199 +0x240 github.com/cometbft/cometbft/p2p.(*Switch).addPeer() /Users/hh/go/src/github.com/cometbft/cometbft/p2p/switch.go:855 +0x7b4 github.com/cometbft/cometbft/p2p.(*Switch).acceptRoutine() /Users/hh/go/src/github.com/cometbft/cometbft/p2p/switch.go:707 +0x704 github.com/cometbft/cometbft/p2p.(*Switch).OnStart.func1() /Users/hh/go/src/github.com/cometbft/cometbft/p2p/switch.go:241 +0x34 Goroutine 130 (running) created at: github.com/cometbft/cometbft/consensus.(*Reactor).AddPeer() /Users/hh/go/src/github.com/cometbft/cometbft/consensus/reactor.go:198 +0x164 github.com/cometbft/cometbft/p2p.(*Switch).addPeer() /Users/hh/go/src/github.com/cometbft/cometbft/p2p/switch.go:855 +0x7b4 github.com/cometbft/cometbft/p2p.(*Switch).acceptRoutine() /Users/hh/go/src/github.com/cometbft/cometbft/p2p/switch.go:707 +0x704 github.com/cometbft/cometbft/p2p.(*Switch).OnStart.func1() /Users/hh/go/src/github.com/cometbft/cometbft/p2p/switch.go:241 +0x34 ================== ``` --- #### PR checklist - [ ] Tests written/updated - [x] Changelog entry added in `.changelog` (we use [unclog](https://github.com/informalsystems/unclog) to manage our changelog) - [ ] Updated relevant documentation (`docs/` or `spec/`) and code comments (cherry picked from commit 587bc0b) # Conflicts: # .changelog/v0.37.0/bug-fixes/524-rename-peerstate-tojson.md * Move changelog entry to correct folder Signed-off-by: Thane Thomson <connect@thanethomson.com> --------- Signed-off-by: Thane Thomson <connect@thanethomson.com> Co-authored-by: Mark Rushakoff <mark.rushakoff@gmail.com> Co-authored-by: Thane Thomson <connect@thanethomson.com>
3 tasks
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This is an automatic backport of pull request #524 done by Mergify.
Cherry-pick of 587bc0b has failed:
To fix up this pull request, you can check it out locally. See documentation: https://docs.github.com/en/github/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally
Mergify commands and options
More conditions and actions can be found in the documentation.
You can also trigger Mergify actions by commenting on this pull request:
@Mergifyio refresh
will re-evaluate the rules@Mergifyio rebase
will rebase this PR on its base branch@Mergifyio update
will merge the base branch into this PR@Mergifyio backport <destination>
will backport this PR on<destination>
branchAdditionally, on Mergify dashboard you can:
Finally, you can contact us on https://mergify.com