Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ directory is `issues/every-program-sees-only-the-files-it-was-given.md`'s.
cleanup without cooperation, run on the causing path in bounded steps. init
never dies and stays tiny.

**Ruled** (owner, 2026-10-21): libc's signals are the focused set this track
plans, over native process events: a child's end (stage 4) and an interrupt,
hang-up or terminate request (stage 6), and no POSIX signal subsystem up
front. libc's adaptation stays in userland, and ordinary Rust behaviour is
kept. Further signal behaviour comes when a required program shows a
concrete need, with its semantics and cost reviewed then. An unsupported
signal operation never appears to succeed
(`issues/libc-sigaction-answers-success-and-keeps-nothing.md`).

## Stages

1. **Done** (#926, stage 1.2 of
Expand Down
26 changes: 23 additions & 3 deletions issues/a-stream-cannot-move-between-processes.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,30 @@ starts (`sdk/toyos/src/spawn.rs`, `sdk/toyos/src/fd.rs`'s `copy`,
A program that hands a stream to another process, as an inetd-style server
does through its child's stdio, fails on ToyOS where it works elsewhere, and
one that takes a moved stream back as a `TcpStream`, as socket activation
does, is refused, though root `CLAUDE.md` says existing Rust just works.
does, is refused, though root `CLAUDE.md` says existing Rust just works. What
replaces the refusal is a socket shared by its holders, not moved, as the
ruling below says.

**Ruled** (owner, 2026-10-21): sharing, inheritance and the surviving holders
are preserved: a socket given to a child stays the parent's too, and the
others keep working when one holder exits or is killed. Neither resetting
every holder's connection when one is interrupted nor a temporary refusal to
give a socket to a child is approved. Nginx's shared listeners establish its
inheritance and lifetime requirements. The ruling covers every socket kind,
so listeners and datagram sockets are shared as streams are.

Planning's reading of the evidence (2026-10-21): data a dead holder already
consumed need not be recovered.

The sharing and recovery design is engineering's and under review, outside
the tree. It proposes, and nobody has accepted, that the descriptor work's
spawn from the table (PR 4) lands after its stages for shared streams,
listeners and datagrams, and unconnected C sockets, since every interim rule
for an inheritable socket is rejected or unapproved.

Owner: the orchestrator, who stages
`issues/netstack-moves-every-byte-through-two-kernel-pipes.md`.

Exit: a stream moved by its handle reads and writes in the receiving process,
and the process that moved it holds no end.
Exit: a stream, a listener and a datagram socket given to a child read, write
and accept in both processes at once, and each keeps working in the survivor
when the other holder exits or is killed.
30 changes: 30 additions & 0 deletions issues/an-unlinked-open-file-answers-stale.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
status: open
kind: track
opened: 2026-10-22
---

# An unlinked open file answers Stale

A file the file server holds open answers `Stale` from the moment its name is
unlinked or renamed over (`system/fileserver/src/volume.rs`, the module
header), and a test asserts it. POSIX's file lives on until its last close or
unmap, and SQLite relies on that: it opens every temporary file and unlinks it
at once, and its last connection unlinks the `-shm` file while it is still
mapped. So any SQLite statement that spills to a temporary file fails today,
cargo's bundled one included.

**Ruled** (owner, 2026-10-21):
removing the last directory name prevents fresh opens through that name, and
existing handles and mappings keep the same file until their final release. A
new file made at the old path is a different file and never retargets them.
The file server owns the lifetime and the storage's reclaim; the kernel keeps
no filesystem identity or naming.

**Exit**: a file unlinked while open, and one renamed over, is read and written
through its open descriptor until the last goes, and its blocks are freed
then; a crash leaves the orphans for the next mount to reclaim; each asserted
by the file server's host volume tests, replacing today's `Stale` test
(`system/fileserver/src/data.rs`). A guest test reads a mapping of an
unlinked file once file mappings exist
(`issues/process-memory-is-2-mib-pages-and-that-caps-the-process-count.md`).
18 changes: 18 additions & 0 deletions issues/libc-answers-st-nlink-0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
status: open
kind: defect
opened: 2026-10-22
---

# libc answers st_nlink 0

libc's `stat`, `lstat` and `fstat` (`sdk/libc/src/posix_io.rs`, `answered`)
zero the whole `struct stat` and never set `st_nlink`, so every file has no
link. Neither the kernel's `/tmp` nor the file server has hard links, so the
true count is 1.
SQLite checks every database it opens (`verifyDbFile` in `os_unix.c`): a
count of 0 is logged as a file unlinked while open, and one past 1 as a file
with several names.

**Exit**: a file and a directory answer `st_nlink` 1 on `/tmp`, `/system` and a
served directory, in a C corpus case.
25 changes: 25 additions & 0 deletions issues/libc-answers-uid-0-for-every-process.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
status: open
kind: defect
opened: 2026-10-22
---

# libc answers uid 0 for every process

libc's `getuid`, `geteuid`, `getgid` and `getegid` answer 0
(`sdk/libc/src/misc.rs`), and `stat` answers `st_uid` and `st_gid` 0, so every
C program believes it runs as root. PostgreSQL
refuses to start as root, and sshd and other daemons take root as a right
they hold.

**Ruled** (owner, 2026-10-21):
libc reports the process's actual ToyOS user identity, through one userland
mapping from the authenticated identity to user and group ids, and never
another invented constant. No Unix root authority enters the kernel:
capabilities remain the authority. Real and effective identity and file
metadata stay coherent, and an unsupported identity change fails honestly.
The identity it maps is `issues/a-user-is-a-home-tree-and-a-login-row.md`'s.

**Exit**: a C program run by a login reads that user's ids from `getuid`,
`geteuid`, `getgid`, `getegid` and the `st_uid` and `st_gid` of a file it
made, and `setuid` and `setgid` to another id are refused.
19 changes: 19 additions & 0 deletions issues/libc-sigaction-answers-success-and-keeps-nothing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
status: open
kind: defect
opened: 2026-10-22
---

# libc's sigaction answers success and keeps nothing

`signal` and `sigaction` (`sdk/libc/src/misc.rs`) answer success for every
signal but `SIGALRM` and keep nothing: no handler is installed, none runs, and
`oldact` is left as the caller passed it. A program that installs a `SIGINT`,
`SIGTERM` or `SIGCHLD` handler is told it did, and is never called. Which
signals libc delivers, and the ruling that an unsupported one never appears
to succeed, are the process track's
(`issues/a-childs-end-is-an-event-and-a-parent-takes-its-children-down.md`).

**Exit**: `signal` and `sigaction` refuse a handler for a signal libc does not
deliver with `EINVAL`, and keep and answer what they do support, with a C
corpus case and every in-tree caller checked for the false success.
2 changes: 1 addition & 1 deletion issues/no-guest-case-reads-std-filesystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ directory by its path (`issues/remove-all-follows-a-link-swapped-in-mid-walk.md`
Each of libc's is read back by `tests/corpus/tinycc/207_libc_names.c`
and `206_libc_refusals.c`; no C++ program in a guest uses any of it.

Owner: `issues/toyos-builds-itself.md`, M2.
Owner: `issues/toyos-builds-itself.md`, beside its path: no exit there needs it.

**Exit**: a guest test lists a directory through `std::filesystem`, and reads
a file back through `std::ifstream`.
4 changes: 2 additions & 2 deletions issues/remove-all-follows-a-link-swapped-in-mid-walk.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ holds a descriptor for each directory and resolves every name against it
`AT_REMOVEDIR`), and ToyOS has no such descriptor: `open` refuses every
directory, and the kernel resolves every path from the root.

Owner: `issues/toyos-builds-itself.md`, M2, whose clang brought
`std::filesystem` in.
Owner: `issues/toyos-builds-itself.md`, beside its path, since no exit there
needs it; its M2 clang brought `std::filesystem` in.

**Exit**: a directory opens as a handle that the kernel resolves names
against, libc defines `openat`, `fdopendir` and `unlinkat` over it, and
Expand Down
65 changes: 65 additions & 0 deletions issues/sqlite-and-postgresql-run-on-toyos.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
status: open
kind: track
opened: 2026-10-22
---

# SQLite and PostgreSQL run on ToyOS

SQLite, as first-release applications bundle it, and later PostgreSQL and
Nginx run on ToyOS with their own semantics.

**Ruled** (owner, 2026-10-21; decisions, not implementation claims):

- **SQLite uses its stock Unix VFS** through ToyOS libc, including the copies
applications bundle; a ToyOS-specific SQLite VFS is not required. The file
server and the SDK supply the native file, locking, mapping and durability
contracts, and libc adapts them in userland; no Unix filesystem policy
enters the kernel. Multiprocess WAL, locking and durable I/O are validated,
not startup alone.
- **An unlinked open file lives on** until its last release:
`issues/an-unlinked-open-file-answers-stale.md`.
- **PostgreSQL starts its processes by `EXEC_BACKEND` over native spawn**,
with the adaptation in PostgreSQL's platform port. No `fork` and no
address-space cloning are added for it.
- **A shared segment is placed by the spawner:** the parent installs the
authorised shared object at a requested address in the child before it
starts. An overlap is refused and reported as a startup failure; rights,
range, protection and accounting are enforced; address randomisation is
unchanged for other mappings. The exact interface is engineering's.
- **Identity:** `issues/libc-answers-uid-0-for-every-process.md`. PostgreSQL's
ownership checks keep their security purpose under native grants.
- **Signals** are the process track's
(`issues/a-childs-end-is-an-event-and-a-parent-takes-its-children-down.md`).
PostgreSQL's own signal table is not approved in its details.
- **Scope:** PostgreSQL and Nginx may arrive after the first release, but
constrain design now; SQLite for first-release applications is unaffected.

**Delegated** (planning, 2026-10-21, under the owner's delegation; open to
the owner's challenge):

- **Wake-ups between PostgreSQL's processes** are userland coordination over
the existing wait and wake primitives: no lost wake-up, no busy polling and
no kernel mechanism for PostgreSQL alone.
- **Launch** is the existing launch and service lifecycle: no `system.toml`
row is required, no quit reason is added for a database, and native quit
requests are honoured.
- **No version, connection target or patch-size cap** is a product
requirement; engineering pins versions for feasibility work and reports the
limits.

**What SQLite needs**: record locks the file server serves
(`issues/std-file-lock-answers-ok-and-locks-nothing.md`), unlink-while-open,
`O_EXCL` on `/tmp` (`issues/create-new-on-a-kernel-path-is-not-exclusive.md`),
`st_nlink` 1 (`issues/libc-answers-st-nlink-0.md`), a sub-second clock
(`issues/userlands-wall-clock-has-whole-seconds-and-an-mtime-has-nanoseconds.md`)
and a directory `fsync`, which this track owns: SQLite syncs a directory after
the unlink that commits a transaction in its default journal mode, and
ignores only a directory it cannot open. WAL also needs coherent shared file
mappings (`issues/process-memory-is-2-mib-pages-and-that-caps-the-process-count.md`).
`issues/toyos-builds-itself.md` orders those cargo's SQLite needs too.

**Exit**: SQLite's own test harness, built for ToyOS from upstream with the
stock unix VFS, passes its multiprocess WAL, locking and durability tests in a
guest; and PostgreSQL's regression suite passes against a cluster started by
the port.
Loading