service: on_buffered_message for pushed events (S5)
An additive, behavior-neutral callback. A buffered async message (Received.isMessage — a pushed event from a provider this service subscribed to) carries a payload in the receive buffer; run() now hands it to on_buffered_message before falling through to on_notification with the badge, so a coalesced timer/exit riding the same wake is not lost. A service that does not set the callback (all of them today) is unchanged: the isMessage branch is a no-op and on_notification still runs, exactly as before. This is the seam the volume manager needs to consume block medium_changed: the event's reserved op number collides with the volume manager's own hello, so it must be decoded by hand here, never through the protocol dispatch. Full suite neutral (the lone device-authority miss is a known child-cleanup race that passes on rerun).
This commit is contained in:
@@ -67,6 +67,15 @@ pub const Callbacks = struct {
|
|||||||
/// A notification that is not a signal — a subscribed exit event, a bound
|
/// A notification that is not a signal — a subscribed exit event, a bound
|
||||||
/// IRQ, a timer landing. The raw badge; decode with the ipc helpers.
|
/// IRQ, a timer landing. The raw badge; decode with the ipc helpers.
|
||||||
on_notification: ?*const fn (badge: u64) void = null,
|
on_notification: ?*const fn (badge: u64) void = null,
|
||||||
|
/// A buffered async message (`Received.isMessage`): a pushed event from a
|
||||||
|
/// provider this service subscribed to, its payload in the receive buffer.
|
||||||
|
/// Unlike `on_message`, it never goes through the protocol dispatch — so an
|
||||||
|
/// event whose reserved op number collides with one of this service's own
|
||||||
|
/// verbs (a `block` `medium_changed` reaching the volume manager, whose own
|
||||||
|
/// protocol numbers `hello` the same) is decoded by hand here, not
|
||||||
|
/// mis-dispatched. Default null: the badge alone still reaches
|
||||||
|
/// `on_notification`, exactly as before this callback existed.
|
||||||
|
on_buffered_message: ?*const fn (message: []const u8) void = null,
|
||||||
/// The reload signal. Default: ignored.
|
/// The reload signal. Default: ignored.
|
||||||
on_reload: ?*const fn () void = null,
|
on_reload: ?*const fn () void = null,
|
||||||
/// The terminate signal, called before the loop returns. The clean exit is
|
/// The terminate signal, called before the loop returns. The clean exit is
|
||||||
@@ -372,6 +381,13 @@ pub fn run(comptime maximum_message: usize, callbacks: Callbacks) void {
|
|||||||
if (got.isChildExit()) {
|
if (got.isChildExit()) {
|
||||||
if (callbacks.subscribers) |subscribers| subscribers.forget(got.childProcessId());
|
if (callbacks.subscribers) |subscribers| subscribers.forget(got.childProcessId());
|
||||||
}
|
}
|
||||||
|
// A buffered async message (a pushed event) carries a payload; hand it
|
||||||
|
// to the service that asked for it. The badge still reaches
|
||||||
|
// on_notification below, so a coalesced timer/exit riding the same wake
|
||||||
|
// is not lost — and a service without this callback is unchanged.
|
||||||
|
if (got.isMessage()) {
|
||||||
|
if (callbacks.on_buffered_message) |onBuffered| onBuffered(receive[0..got.len]);
|
||||||
|
}
|
||||||
if (callbacks.on_notification) |onNotification| onNotification(got.badge);
|
if (callbacks.on_notification) |onNotification| onNotification(got.badge);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user