Instance Forking
Instance forking is a preview feature and isn't yet available on stable. The interface described here reflects the current implementation and may change before general availability.
Instance forking lets a running instance create an independent copy of itself at a snapshot boundary.
Both the original instance (the parent) and the copy (the child) resume execution from the same memory state.
This works like fork(2) in a POSIX process.
The app inside an instance triggers the fork through a filesystem interface.
Filesystem interface
The fork interface uses a FUSE (Filesystem in Userspace) filesystem mounted at /uk/libukp inside every instance.
Apps trigger forks and track child instances by reading and writing (ASCII) files in this filesystem.
The filesystem exposes the following top-level entries:
| Path | Read | Write | Description |
|---|---|---|---|
/uk/libukp/fork | Returns the child UUID after a fork (for the parent), or empty (for the child). | Triggers a new fork operation. | Main entry point for forking. |
/uk/libukp/vm/ | Directory listing of all child instance UUIDs. | — | Each child gets a subdirectory named by its UUID. |
Triggering a fork
To fork the current instance, write any value to the fork file:
Code
The write blocks until the platform completes the fork. When it returns, the parent can read the child's UUID from the same file:
Code
For the child instance, reading /uk/libukp/fork returns a zero UUID.
This is how an app determines whether it's the parent or the child after a fork.
Concurrent fork requests
The ukp-fuse daemon serializes fork operations.
Only one fork can run at a time.
If a second fork request arrives while one runs, the daemon queues it.
If the queue fills up, the write returns EBUSY.
The daemon processes queued requests in order once the current fork completes.
Tracking child instances
After a fork, a new directory appears at /uk/libukp/vm/<child-uuid>/ containing files that reflect the child's state:
| File | Read | Write | Description |
|---|---|---|---|
snapshot | Snapshot UUID the child originates from. | — | Read-only. |
creation_time | Unix timestamp (seconds since epoch) of child creation. | — | Read-only. |
status | Current state: Starting, Running, Draining, Stopping, Stopped, or Template. | — | Read-only. |
wait | Exit code of the child (available once stopped). | Write any value to begin waiting for the child to stop. | Supports poll() for non-blocking use. Returns POLLIN when the exit code becomes available. |
Waiting for a child to stop
To block until a child instance exits:
Code
The write to wait blocks until the child stops.
After the write completes, reading wait returns the numeric exit code.
If the child has already stopped by the time you write to wait, the write completes immediately.
Many processes can wait on the same child concurrently. The daemon notifies each one when the child exits.
For non-blocking usage, poll() on the wait file descriptor returns POLLIN when the exit status becomes available.
Checking child status
To inspect a child's current state without blocking:
Code
The platform updates the status file in real time.
Possible states and their numeric values:
| State | Description |
|---|---|
Stopped | Instance has exited. |
Starting | Instance is booting. |
Running | Instance is running. |
Draining | Instance is draining connections before stopping. |
Stopping | Instance is shutting down. |
Template | Instance has become a template. |
Child lifecycle
- Children have
delete-on-stopenabled automatically. The platform removes them when they stop. - The child's
/uk/libukp/vm/directory starts empty. The child doesn't inherit any children from the parent—it only sees children from forks it starts itself. - A parent can have many children alive at the same time.
- A child can itself fork, becoming a parent to its own children.
Error handling
| Error | Cause |
|---|---|
EBUSY | Fork queue is full. |
EIO | Hardware signal to the platform failed, or the request belonged to a parent before a fork occurred. |
ESTALE | A child VM directory access occurred after the child's cleanup (for example, after the current instance became a child via fork). |
Constraints
- The REST API and
kraftcan't trigger a fork. You must start it from within the instance via the/uk/libukp/forkfile.
Learn more
- Instance templates: a related snapshot-based feature for creating instances from a stopped template
- Instances