FAILURE MAP
← Case archive

FA-276 / Runtime and resources / Open access

Callback duration accumulates into periodic task drift · case 01

A task sleeps a full period after finishing, or the attempted correction schedules overlapping callbacks.

Verified by executionVariant 1 · 7 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

Release times are derived from completion without preserving the original phase and nonoverlap policy.

VERIFIED REPAIR

Choose the first original-phase deadline at or after completion, strictly later than the preceding start.

Unsuccessful approach: Incrementing by exactly one period preserves phase but ignores missed deadlines after an overrun.

Case contract

Period is a positive integer, start and durations are nonnegative integers. The first callback starts at start. Later starts are the earliest start+k*period >= preceding completion and strictly greater than preceding start. Missed slots are skipped, not caught up. Return one start per duration.

Why this case matters

Models a fixed-phase periodic scheduler with nonoverlapping callbacks; it separates arithmetic policy from OS scheduling, clock drift, and real-time execution guarantees.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(period, start, durations):
    times, current = [], start
    for duration in durations:
        times.append(current)
        current += duration+period
    return times
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('short callbacks do not accumulate drift', solve(10*N, 0, [N]*3), [0, 10*N, 20*N])
check('overrun skips expired slots', solve(10*N, 0, [25*N, N, N]), [0, 30*N, 40*N])
check('completion exactly on deadline', solve(10*N, 0, [10*N, N]), [0, 10*N])
check('zero-duration still waits a period', solve(N, 0, [0, 0, 0]), [0, N, 2*N])
check('nonzero initial phase preserved', solve(10*N, 3*N, [25*N, N, N]), [3*N, 33*N, 43*N])
check('no callbacks', solve(N, N, []), [])
check('single callback uses initial start', solve(N, 7*N, [100*N]), [7*N])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
short callbacks do not accumulate drift[0, 11, 22][0, 10, 20]Failed
overrun skips expired slots[0, 35, 46][0, 30, 40]Failed
completion exactly on deadline[0, 20][0, 10]Failed
zero-duration still waits a period[0, 1, 2][0, 1, 2]Passed
nonzero initial phase preserved[3, 38, 49][3, 33, 43]Failed
no callbacks[][]Passed
single callback uses initial start[7][7]Passed

SHA-256 / a63c369fb4af8e8aa2d2eba1aa0d231a174bbb31efa58fd76cb3037c64cad6c9

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(period, start, durations):
    return [start+i*period for i in range(len(durations))]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('short callbacks do not accumulate drift', solve(10*N, 0, [N]*3), [0, 10*N, 20*N])
check('overrun skips expired slots', solve(10*N, 0, [25*N, N, N]), [0, 30*N, 40*N])
check('completion exactly on deadline', solve(10*N, 0, [10*N, N]), [0, 10*N])
check('zero-duration still waits a period', solve(N, 0, [0, 0, 0]), [0, N, 2*N])
check('nonzero initial phase preserved', solve(10*N, 3*N, [25*N, N, N]), [3*N, 33*N, 43*N])
check('no callbacks', solve(N, N, []), [])
check('single callback uses initial start', solve(N, 7*N, [100*N]), [7*N])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
short callbacks do not accumulate drift[0, 10, 20][0, 10, 20]Passed
overrun skips expired slots[0, 10, 20][0, 30, 40]Failed
completion exactly on deadline[0, 10][0, 10]Passed
zero-duration still waits a period[0, 1, 2][0, 1, 2]Passed
nonzero initial phase preserved[3, 13, 23][3, 33, 43]Failed
no callbacks[][]Passed
single callback uses initial start[7][7]Passed

SHA-256 / 37f47245ca578d2ca39323b4c4f17d14fcbae07652801a422f0f1ea7d594d17c

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(period, start, durations):
    times, slot = [], 0
    for duration in durations:
        current = start+slot*period
        times.append(current)
        completed = current+duration
        slot = max(slot+1, (completed-start+period-1)//period)
    return times
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('short callbacks do not accumulate drift', solve(10*N, 0, [N]*3), [0, 10*N, 20*N])
check('overrun skips expired slots', solve(10*N, 0, [25*N, N, N]), [0, 30*N, 40*N])
check('completion exactly on deadline', solve(10*N, 0, [10*N, N]), [0, 10*N])
check('zero-duration still waits a period', solve(N, 0, [0, 0, 0]), [0, N, 2*N])
check('nonzero initial phase preserved', solve(10*N, 3*N, [25*N, N, N]), [3*N, 33*N, 43*N])
check('no callbacks', solve(N, N, []), [])
check('single callback uses initial start', solve(N, 7*N, [100*N]), [7*N])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
short callbacks do not accumulate drift[0, 10, 20][0, 10, 20]Passed
overrun skips expired slots[0, 30, 40][0, 30, 40]Passed
completion exactly on deadline[0, 10][0, 10]Passed
zero-duration still waits a period[0, 1, 2][0, 1, 2]Passed
nonzero initial phase preserved[3, 33, 43][3, 33, 43]Passed
no callbacks[][]Passed
single callback uses initial start[7][7]Passed

SHA-256 / fe5d579cc2759bea5826660ad90da1b274e30b5810068420fb44c8106cc62878

Verification & scope

This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:36:51.597394+00:00.

Case digest / cc94d8179fca17076565de39d7ea1c1d7a60f38649ad9167280aa78828461da0