1 Commits

Author SHA1 Message Date
funman300 c3addde9b1 Correct FIFA17 SBC dispatch notifier lifecycle guard to post-exit invariant 2026-08-18 20:59:07 +00:00
+17 -3
View File
@@ -180,9 +180,15 @@ fn decide(input: DecisionInput) -> Result<Decision, Rejection> {
if input.live_category_count != input.category_count {
return Err(Rejection::ModelChanged);
}
// The category-success notifier for this generation must have entered and
// fully returned before the SBC completion runs. On the pinned CardsDLL the
// completion fires immediately after the notifier unwinds (measured: notifier
// entries == exits == generation at completion), not nested inside it, so we
// bind both notifier counts to the current generation rather than requiring
// an in-flight notifier.
if input.notifier_entries != generation
|| input.notifier_entries == 0
|| input.notifier_exits.checked_add(1) != Some(input.notifier_entries)
|| input.notifier_exits != generation
{
return Err(Rejection::NotifierNotCurrent);
}
@@ -730,7 +736,7 @@ mod tests {
live_category_count: 2,
category_count: 2,
notifier_entries: generation,
notifier_exits: generation - 1,
notifier_exits: generation,
controller_matches: true,
controller_model_matches: true,
last_repaired_generation: generation - 1,
@@ -776,8 +782,16 @@ mod tests {
input.status = None;
assert_eq!(decide(input), Err(Rejection::StatusUnreadable));
// Notifier still in flight for this generation (has not returned) is rejected:
// on the pinned build the completion only runs after the notifier unwinds.
let mut input = valid_input(1);
input.notifier_exits = 1;
input.notifier_exits = 0;
assert_eq!(decide(input), Err(Rejection::NotifierNotCurrent));
// A notifier count that does not match the current generation is rejected.
let mut input = valid_input(1);
input.notifier_entries = 2;
input.notifier_exits = 2;
assert_eq!(decide(input), Err(Rejection::NotifierNotCurrent));
let mut input = valid_input(1);