diff --git a/src/acquisition.cpp b/src/acquisition.cpp index 93640a5..4c9c774 100644 --- a/src/acquisition.cpp +++ b/src/acquisition.cpp @@ -462,6 +462,16 @@ void Acquisition::on_data(const udps_frame_t* frame) { have_counter_ = true; } + // A late frame's samples belong in the hole already reserved for them, not at the end of + // the timeline. Appending them would walk the time ring's clock backwards, which trips the + // non-monotonic guard and can throw the whole stream onto the arrival clock -- a far worse + // outcome than the dropped packet we used to have. Until the backfill lands (RingBuffer::amend + // and MinMaxPyramid::amend), late frames are dropped here, leaving the reserved hole holding + // the NaN it was reserved with -- a value every reader already treats as absent. This is + // exactly the behaviour the client had before it started delivering late packets, so nothing is + // lost relative to that. This return is the single place the backfill will later hook into. + if (frame->late) return; + const Partition& part = model_.partition(); const std::vector& channels = model_.channels(); if (part.time_capacity == 0 || channels.empty()) return;