Skip to content

Commit 89afc26

Browse files
committed
Avoid taking the write-lock on val monitor
1 parent b84ff9f commit 89afc26

File tree

2 files changed

+30
-4
lines changed

2 files changed

+30
-4
lines changed

beacon_node/beacon_chain/src/validator_monitor.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,16 @@ impl<T: EthSpec> ValidatorMonitor<T> {
440440
.and_then(|pubkey| self.validators.get(pubkey))
441441
}
442442

443+
/// Return `true` if the `validator_index` has been registered with `self`.
444+
pub fn contains_validator(&self, validator_index: u64) -> bool {
445+
self.indices.contains_key(&validator_index)
446+
}
447+
448+
/// Return `true` if the automatic validator registration is enabled.
449+
pub fn auto_register_enabled(&self) -> bool {
450+
self.auto_register
451+
}
452+
443453
/// Returns the number of validators monitored by `self`.
444454
pub fn num_validators(&self) -> usize {
445455
self.validators.len()

beacon_node/http_api/src/lib.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1877,10 +1877,26 @@ pub fn serve<T: BeaconChainTypes>(
18771877
chain: Arc<BeaconChain<T>>| {
18781878
blocking_json_task(move || {
18791879
for subscription in &subscriptions {
1880-
chain
1881-
.validator_monitor
1882-
.write()
1883-
.auto_register_local_validator(subscription.validator_index);
1880+
// Assign the result from the read to a separate variable, to avoid a Rust
1881+
// quirk where a read-lock obtained inside an `if` statement is for the
1882+
// execution inside it.
1883+
//
1884+
// Checking the read-lock first helps avoid lengthy waits for the
1885+
// write-lock. Although another thread may add the validator between
1886+
// dropping the read-lock and obtaining the write-lock, there's no harm in
1887+
// registering the same validator twice.
1888+
let should_register = {
1889+
let validator_monitor = chain.validator_monitor.read();
1890+
validator_monitor.auto_register_enabled()
1891+
&& validator_monitor
1892+
.contains_validator(subscription.validator_index)
1893+
};
1894+
if should_register {
1895+
chain
1896+
.validator_monitor
1897+
.write()
1898+
.auto_register_local_validator(subscription.validator_index);
1899+
}
18841900

18851901
let subscription = api_types::ValidatorSubscription {
18861902
validator_index: subscription.validator_index,

0 commit comments

Comments
 (0)