library: the harness keeps the subscribers, and an id belongs to whoever opened it
Three services had each written the same thing and got it three different ways: input polled the process list to notice a dead subscriber, and only when someone else subscribed; the power service never noticed at all; the device manager noticed drivers but not subscribers. The harness owns the table now, driven by the events a protocol declares — it registers on the reserved verb, frames each event once, posts to everyone interested without waiting on any of them, and reclaims a slot when the kernel says its owner died. Interest masks moved to the envelope, so a subscriber that wants only mice asks the same way everywhere. Two consequences the plan had not foreseen. The device manager now hears a supervised child's death twice, once as its supervisor and once as a subscriber, so restart backoff counted every crash twice and gave up after half as many; it retires the id before counting. And the kernel's published exit table had eight slots for what is now six subscriptions in a plain boot, so it holds sixteen. The other half is a hole the design named early and left standing: a backend handed out a small integer and then honoured it from anyone. A process that guessed a file's node id read another client's file; a display layer had no owner at all, so any client could reconfigure or destroy any layer; a USB device token was never checked against the client that opened it. Each is now bound to the task that opened it, and a wrong owner gets exactly what an unknown id gets — the refusal must not become the oracle the identical answers elsewhere were designed to remove. Closing a file changed with it: it used to succeed unconditionally, which would have told a caller which ids existed. Suite 111/111, with a new case in which one process holds a file and a layer, hands both ids to a second process, and finds them untouched after that process has tried everything with them.
This commit is contained in:
@@ -211,6 +211,18 @@ shell, a terminal, a cursor, and a wallpaper:
|
||||
| `damage` | mark a region of a layer dirty |
|
||||
| `present` | request a repaint: composited at the next frame-clock tick |
|
||||
|
||||
**A layer belongs to the client that created it.** The id is a slot in a
|
||||
sixteen-entry table — small, dense, guessable — so every verb above that names one is
|
||||
answered only for the task whose `create_layer` produced it, and a layer that is
|
||||
somebody else's is refused exactly as one that never existed (`-ENOENT`), so a client
|
||||
cannot use the refusal to learn which ids are live
|
||||
([protocol-namespace.md](../os-development/protocol-namespace.md): handles are scoped
|
||||
per client, validated against the badge). The compositor's own layers — the cursor
|
||||
sprite and the startup self-check's pair — are marked service-owned and are created by
|
||||
direct call rather than over the protocol, so no client can move or destroy the
|
||||
cursor. A dead client's layers are released on its exit notification, the same sweep
|
||||
the FAT server runs for open files.
|
||||
|
||||
Text is intentionally *not* an operation — a client renders glyphs by blitting tiles
|
||||
(the [PSF font](../../system/kernel/font.psf) path the console already uses can move into a
|
||||
client). Keeping the protocol to rectangles and tiles keeps the compositor small and the
|
||||
|
||||
Reference in New Issue
Block a user