-
Notifications
You must be signed in to change notification settings - Fork 20.7k
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
eth/catalyst: avoid a race in the SimulatedBeacon Stop call #31328
base: master
Are you sure you want to change the base?
Conversation
This allows the inner loop in the case of "on-demand" commits to bail out if the txPool has been terminated before the doCommit channel is closed. This has been tested with a known-flaky test which, before this commit was spinlooping and logging unfathomable reams of warning messages. Now, when the race occurs, only a single instance of the warning is logged.
The irony of requiring two commits instead of one to introduce a function called |
So the thing is... a failure from |
Well-spotted. So, this makes me want to go back to calling Sync() because that's the code that actually can only error when the txPool has already terminated. Another option would be to create a special error type to be returned from Sync() when the pool is already terminated, then, conditionally break from the spinloop only if the error from fallibleCommit is of that new type. Sound like a plan? If so, I'll get to coding. |
Let's just use a call to |
actually, I would:
|
This way, we only break the spinloop when it is definitely because the transaction pool has already been terminated.
Okay. Now, it's doing what you suggested. Thanks for the advice. |
This addresses some review feedback.
eth/catalyst/simulated_beacon.go
Outdated
@@ -181,7 +192,7 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u | |||
// behavior, the pool will be explicitly blocked on its reset before | |||
// continuing to the block production below. | |||
if err := c.eth.APIBackend.TxPool().Sync(); err != nil { | |||
return fmt.Errorf("failed to sync txpool: %w", err) | |||
return &errTxPoolTerminated{fmt.Errorf("failed to sync txpool: %w", err)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would just turn it into, not really a need for wrapping another error type errTxPoolTerminated error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I fear that I have not clearly undrestood this suggestion. But, I did something to move the "failed to sync txpool:" part of the message into the errTxPoolTerminated.Error
implementation.
I think the general approach here is fine, and we should merge this (after cleaning up the error checking, RE comments from Marius). But just a thought: maybe a cleaner solution that accomplishes the same thing would be to add a member method |
Use `errors.Is` instead of `errors.As` since we don't need to access special fields in the custom error type. Rather than generating a new error to wrap, just capture the exisitng error.
I'm definitely open to switching to that implementation instead. But, I "slightly" prefer the existing one. I think library APIs are best when you don't need to remember to make multiple calls to the library to get the information the calling code needs to make progress. With the error-handling approach, it is clear that the work we're trying to do is |
Fixes: #31327