DrumsBench

Experiments / EXP-008

Custom rootfs runtime (the Drums candidate arm on Linux), CRIU dump and restore attempts of the GNOME tree

Run the pinned OSWorld image's own userland (dbus, Xorg, GNOME, guest server) as a shared-kernel slot and checkpoint and restore it with CRIU 4.3 under the same validity gates as the VM baseline.

failedRan and missed a correctness, isolation, reset or pre-registered performance bar. Kept on the record.
Date
2026-10-25
Hypothesis
A pivot_rooted overlay slot with the image's own supervisor can be dumped and restored by CRIU with its locks, mounts and network state preserved.
Arms
drums-rootfs-criu
Hardware
operator's root Linux host, not identified on the branch (kernel reported as 7.0-aws in PROTOCOL.md)
OS
host Ubuntu 24.04 (CRIU built from source); slot userland: OSWorld Ubuntu 22.04.3 image
Workload
OSWorld task e0df059f (folder rename) through the slot's own guest server
Code
claude/ecstatic-archimedes-456go6 at fd39055
Limitation
Every dump and restore described here is author-claimed in docs and commit messages with no log, image manifest or census file on the branch; no restore of the GNOME tree has passed its gates, so this is not yet a working Drums runtime.

In one paragraph

This is the arm that is supposed to become Drums on Linux: not a VM and not an OCI container, but a process tree on the host kernel built from an overlay of the OSWorld image, running the image's own GNOME desktop and guest server, checkpointed by calling CRIU directly. Over about six hours on 2026-10-25 the author took it through a series of real dumps and restores on an operator host. Each attempt failed at a new gate, each failure was fixed in source, and the last one reached a restore that CRIU itself called successful but that our lock gate rejected because a POSIX lock on a mapped file was missing (EXP-009). Every number and error line in this record is author-claimed, no log on branch. The runtime has never completed a passing snapshot and restore cycle. It is not yet a working Drums runtime, and nothing here compares it with anything.

Setup

What the slot runtime is

Mechanism, from the branch README and CANDIDATE.md:

Declared differences from the OCI control

itemOCI control (runc 1.5.2 + CRIU 4.3, EXP-010)this candidate
who builds namespaces, mounts, devices, session, cgrouprunc from an OCI config.jsonthe repo's tree init and a systemd scope
how CRIU is invokedrunc RPC, criu-root bind, notify scripts, external mount mapsdirectly, no RPC, no external mounts
--root at restorebind of the container rootfs in runc's mount namespacea fresh overlay mount in a private mount namespace
device nodesbound from the host as external mountsprivate native mknod nodes on a tmpfs
network namespaceharness-owned holder process, not in the CRIU imagecheckpointed by CRIU, part of the image
--file-locksforwarded by runc, default falseadded to dump and restore only when the pre-dump census proves every lock is enclosed
dependency footprintrunc binary and OCI bundlenone beyond CRIU and the host's unshare, systemd-run, qemu-nbd

Shared with the control, so not a differentiator: the same pinned image, overlayfs, the same supervisor and services, the same cgroup limits, the same CRIU 4.3, the same acceptance gates. CANDIDATE.md says what is left to compare if both arms ever pass: "overhead (dump/restore time, image size, idle cost without a holder or runc), network fidelity and the dependency footprint. Nothing about that is measured yet, and neither arm is a Drums result until the full workload, CUA and resource accounting exist."

What ran

A sequence of real attempts on the operator host, 14:55 to 18:49 UTC, reconstructed from the README, CANDIDATE.md and commit messages. All author-claimed; no artifact on the branch for any of them.

  1. First real tree dump failed: mnt:403:./dev/tty doesn't have a proper root mount. CRIU's validate_mounts rejects a bind of one host device file. Fix (dc6c015): a plain private tmpfs /dev with native nodes.
  2. Next dump failed: criu/mount.c: The root task has another root than mntns: .../merged. A chroot inside the host's mount namespace is not the namespace root. Fix (b8605b8): pivot_root and the image-side supervisor.
  3. Next dump failed: criu/cr-dump.c: A session leader of 1510 (1) is outside of its pid namespace. The launcher's setsid ran before unshare. Fix (114726b): stage A calls setsid() first and fails closed unless pid == sid == pgid.
  4. Readiness failure inside the chroot: LookupError: unknown encoding: idna from a lazy host import. Fix (c0f4fe5): numeric readiness probe, preloaded modules. Also found: the Xorg log directory was unwritable after Xorg dropped privileges, and the slot user had lost its sudo group because supplementary groups were not taken from the image's /etc/group (both fixed in 97b8727, dc6c015).
  5. First successful dump, then a restore crash (CANDIDATE.md section 1, run on 114726b): dump succeeded in 137 s producing 453 MiB of images (author-claimed, no log on branch); the immediate criu restore died in 0.118 s (author-claimed) after listing host mounts (securityfs, cgroup2, pstore, efivarfs, bpf, debugfs, tracefs), then mount.c:48 BUG, then SIGSEGV. The restore argv had no --root. Source reading: without --root, CRIU's mount-v2 engine tries to unmount the mount table it inherited from CRIU's own (host) namespace and hits BUG_ON(!mi->plain_mountpoint). Fix (846cc7c): the --root restore contract in a private mount namespace.
  6. Candidate arm run (846cc7c): fresh GNOME provision, mount and network readback and the task checker passed before the dump (author-claimed; this is the only place on the branch where a GNOME slot of this runtime is said to have passed the task checker). The dump then failed after 123 s (author-claimed) with Error (criu/file-lock.c:112): Some file locks are hold by dumping tasks! You can try --file-locks to dump them. No restore was reached. CRIU's refusal is a safety check, not a bug. Fix (a84dde4): a pre-dump lock census that adds --file-locks to both dump and restore only when every lock is an advisory lock on a file of the slot's own overlay or tmpfs and no outside process holds or waits on it.
  7. --file-locks run (a84dde4 on 0e16bc5): the census found two Nautilus POSIX READ locks (.../nautilus/tags/meta.db range 1073741826 to 1073742335 and meta.db-shm byte 128), no outside holder. The dump passed in 135 s (author-claimed). The explicit --root restore reported "Restore finished successfully. Tasks resumed." and the mount.c:48 crash did not recur. The strict lock gate then failed: expected 2 READ locks, post-resume census [].
  8. Pre-resume gate run (fd39055): the dump log recorded both locks, the restore log reported applying both ((posix) fd 8 start 0x40000002 len 0x1fe and fd 10 start 0x80 len 1), filelocks.img unchanged, yet CRIU's own pre-resume hook saw only the meta.db lock. The gate was right to fail. This is the open failure recorded in EXP-009.

Results

No measured result. The author-claimed figures, each with no log on the branch: dump 137 s and 453 MiB (step 5), restore crash at 0.118 s (step 5), dump refused after 123 s (step 6), --file-locks dump 135 s (step 7). We do not show these in a result table and nothing should be computed from them.

What the sequence establishes, if the author's text is taken at face value: the tree can be provisioned to a GNOME desktop that passes the OSWorld task checker before any snapshot; CRIU 4.3 accepts the whole tree for dump once /dev, pivot_root, session ownership and --file-locks are right; a --root restore completes from CRIU's point of view. What it does not establish: a restored slot that holds every lock it held at dump time, passes the mount and network equality gates, serves the task again and resets. No restore has passed the arm's gates.

Failures and surprises

Limitations

Reproduce

On a root Ubuntu 24.04 host with the image, from benchmark/ (commands from the README; nothing in the sandbox can run them):

sudo ./sharedos_rootfs/host/install_criu.sh --repo "$PWD/.." --evidence /var/lib/drumsbench/criu-install
sudo modprobe nbd max_part=16
sudo python3 -m sharedos_rootfs.image attach --image /data/Ubuntu.qcow2 --expected-sha256 6bf667a8...313 \
    --mountpoint /mnt/osworld --state /var/lib/drumsbench/image-mount.json
python3 -m sharedos_rootfs.rootfs_inspect /mnt/osworld --out /var/lib/drumsbench/inspection.json --mount-state /var/lib/drumsbench/image-mount.json
export SHAREDOS_ROOTFS_CONFIG=/var/lib/drumsbench/rootfs-config.json
sudo -E python3 -m sharedos_rootfs.candidate environment
sudo -E python3 -m sharedos_rootfs.candidate provision --slot 0
sudo -E python3 -m sharedos_rootfs.candidate snapshot --slot 0      # dump + immediate restore, with every gate
sudo -E python3 -m sharedos_rootfs.candidate reset --slot 0
sudo -E python3 -m sharedos_rootfs.candidate cleanup

CANDIDATE.md section 6 asks for a new state directory, the slotN/ evidence plus restore logs to be collected, and "Any failure after the root fix is reported with its log line, not worked around with flags."

Sources