Skip to content

Commit

Permalink
fix patch
Browse files Browse the repository at this point in the history
  • Loading branch information
cl0w committed Oct 16, 2024
1 parent 90da58c commit 4808449
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 48 deletions.
102 changes: 55 additions & 47 deletions substrate/frame/message-queue/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ pub mod pallet {
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn on_initialize(_n: BlockNumberFor<T>) -> Weight {
if let Some(weight_limit) = T::ServiceWeight::get() {
Self::service_queues(weight_limit, ServiceQueuesContext::OnInitialize)
Self::service_queues_impl(weight_limit, ServiceQueuesContext::OnInitialize)
} else {
Weight::zero()
}
Expand All @@ -655,7 +655,10 @@ pub mod pallet {
fn on_idle(_n: BlockNumberFor<T>, remaining_weight: Weight) -> Weight {
if let Some(weight_limit) = T::IdleMaxServiceWeight::get() {
// Make use of the remaining weight to process enqueued messages.
Self::service_queues(weight_limit.min(remaining_weight), ServiceQueuesContext::OnIdle)
Self::service_queues_impl(
weight_limit.min(remaining_weight),
ServiceQueuesContext::OnIdle
)
} else {
Weight::zero()
}
Expand All @@ -676,7 +679,7 @@ pub mod pallet {
/// The context to pass to service_queues through on_idle and on_initialize hooks
/// We don't want to throw the defensive message if called from on_idle hook
#[derive(PartialEq)]
enum ServiceQueuesContext {
pub enum ServiceQueuesContext {
/// Context of on_idle hook
OnIdle,
/// Context of on_initialize hook
Expand Down Expand Up @@ -1486,6 +1489,54 @@ impl<T: Config> Pallet<T> {
}
}

fn service_queues_impl(weight_limit: Weight, context: ServiceQueuesContext) -> Weight {
let mut weight = WeightMeter::with_limit(weight_limit);

// Get the maximum weight that processing a single message may take:
let max_weight = Self::max_message_weight(weight_limit).unwrap_or_else(|| {
if matches!(context, ServiceQueuesContext::OnInitialize) {
defensive!("Not enough weight to service a single message.");
}
Weight::zero()
});

match with_service_mutex(|| {
let mut next = match Self::bump_service_head(&mut weight) {
Some(h) => h,
None => return weight.consumed(),
};
// The last queue that did not make any progress.
// The loop aborts as soon as it arrives at this queue again without making any progress
// on other queues in between.
let mut last_no_progress = None;

loop {
let (progressed, n) = Self::service_queue(next.clone(), &mut weight, max_weight);
next = match n {
Some(n) =>
if !progressed {
if last_no_progress == Some(n.clone()) {
break
}
if last_no_progress.is_none() {
last_no_progress = Some(next.clone())
}
n
} else {
last_no_progress = None;
n
},
None => break,
}
}
weight.consumed()
}) {
Err(()) => weight.consumed(),
Ok(w) => w,
}
}
}

/// Run a closure that errors on re-entrance. Meant to be used by anything that services queues.
pub(crate) fn with_service_mutex<F: FnOnce() -> R, R>(f: F) -> Result<R, ()> {
// Holds the singleton token instance.
Expand Down Expand Up @@ -1553,50 +1604,7 @@ impl<T: Config> ServiceQueues for Pallet<T> {
type OverweightMessageAddress = (MessageOriginOf<T>, PageIndex, T::Size);

fn service_queues(weight_limit: Weight, context: ServiceQueuesContext) -> Weight {
let mut weight = WeightMeter::with_limit(weight_limit);

// Get the maximum weight that processing a single message may take:
let max_weight = Self::max_message_weight(weight_limit).unwrap_or_else(|| {
if matches(context, ServiceQueuesContext::OnInitialize) {
defensive!("Not enough weight to service a single message.");
}
Weight::zero()
});

match with_service_mutex(|| {
let mut next = match Self::bump_service_head(&mut weight) {
Some(h) => h,
None => return weight.consumed(),
};
// The last queue that did not make any progress.
// The loop aborts as soon as it arrives at this queue again without making any progress
// on other queues in between.
let mut last_no_progress = None;

loop {
let (progressed, n) = Self::service_queue(next.clone(), &mut weight, max_weight);
next = match n {
Some(n) =>
if !progressed {
if last_no_progress == Some(n.clone()) {
break
}
if last_no_progress.is_none() {
last_no_progress = Some(next.clone())
}
n
} else {
last_no_progress = None;
n
},
None => break,
}
}
weight.consumed()
}) {
Err(()) => weight.consumed(),
Ok(w) => w,
}
Self::service_queues_impl(weight_limit, ServiceQueuesContext::ServiceQueues)
}

/// Execute a single overweight message.
Expand Down
2 changes: 1 addition & 1 deletion substrate/frame/message-queue/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ fn service_queues_low_weight_defensive() {
assert!(MessageQueue::do_integrity_test().is_err());

MessageQueue::enqueue_message(msg("weight=0"), Here);
MessageQueue::service_queues(104.into_weight());
MessageQueue::service_queues_impl(104.into_weight(), ServiceQueuesContext::OnInitialize);
});
}

Expand Down

0 comments on commit 4808449

Please sign in to comment.