5.6.4 Queues and Overflow
Each armed fd has its own event queue, bounded by
NotificationQueueSize — default 256 events, configurable between 16
and 65536 (§5.10.3).
Delivery is best-effort. A watcher that reads promptly sees every change; one that falls behind is told that it has, rather than being given a partial history it cannot distinguish from a complete one.
5.6.4.1 What happens when the queue is full #
When an event arrives for a full queue and no OVERFLOW is present:
- The oldest queued event is dropped.
- An
OVERFLOWrecord is queued in its place. - The event that triggered this is discarded, not queued.
Once an OVERFLOW is in the queue, subsequent events queue normally:
the oldest non-OVERFLOW event is dropped to make room and the new
event is added, so the single OVERFLOW is preserved and the queue
continues to carry the most recent history behind it.
A queue therefore holds at most one OVERFLOW at a time, and that is
an enforced invariant rather than a convention — an attempt to queue a
second is rejected as a bug.
5.6.4.2 What a watcher does about it #
OVERFLOW means the record it has is incomplete. There is no way to
learn what was dropped, and no attempt is made to describe it. The
watcher re-reads the watched key, and its subtree if the watch is a
subtree watch, and continues from the state it finds. Events after the
OVERFLOW are complete again.
REG_IOC_QUERY_KEY_INFO reports a per-hive generation number
(§5.5.3) that makes this cheaper than it sounds: a watcher that
recorded the generation at its last full read can compare it with the
current one and skip the re-read entirely if nothing committed in
between.
5.6.4.3 Memory #
There is no registry-specific global cap on watch memory, and none is
needed. A watch costs at most NotificationQueueSize queued events, a
watch requires an fd, and a process holds at most RLIMIT_NOFILE fds.
The product of the two is the bound, and it is enforced by machinery
that already exists.
The same reasoning covers open key state: per-fd overhead — GUID, granted mask, ancestor chain, watch state — multiplied by the fd limit.
LCS's own internal watches are outside this. They are delivered synchronously through a kernel callback rather than queued, so the queue limit does not apply to them (§5.10.4).