Skip to content

bincompat-memcached - #114

Merged
razvand merged 4 commits into
unikraft:scriptsfrom
andreea110:add-bincompat-memcached
Aug 22, 2026
Merged

bincompat-memcached#114
razvand merged 4 commits into
unikraft:scriptsfrom
andreea110:add-bincompat-memcached

Conversation

@andreea110

@andreea110 andreea110 commented Jul 9, 2026

Copy link
Copy Markdown

Add bincompat-memcached: run Memcached 1.6 in binary-compatibility mode, modeled on
bincompat-c-hello, with elfloader-net as base.

Root filesystem

rootfs/ builds through Docker, following examples/memcached1.6-base/ in
unikraft/catalog:

  • Dockerfile — multi-stage build on top of the official memcached:1.6.23-bookworm
    image: an alpine:3 stage supplies CA certificates and timezone data, and the final
    scratch stage carries the memcached binary, its dynamic libraries
    (libssl, libcrypto, libevent, libsasl2, libc, ld-linux) and /etc/passwd
    (needed by -u root / getpwnam()).
  • Makefile — runs docker build, then docker create / docker export to extract
    the filesystem into rootfs/extracted_rootfs/.
  • scripts/build/rootfs.x86_64 packs it into initrd.cpio with mkcpio.

Configuration changes

Two options had to be enabled in the elfloader-net defconfigs:

  • CONFIG_LIBPOSIX_FUTEX — without it pthread_create() fails with
    "Unsupported clone flags requested";
  • CONFIG_LIBPOSIX_EVENTFD — Memcached needs eventfd2() for its worker threads.

Also fixes CONFIG_LIBUKBOOT_MAINTHREAD=y=yCONFIG_LIBUKBOOT_MAINTHREAD=y in the
elfloader-basic and elfloader-net defconfigs; the duplicated value is not valid
defconfig syntax.

Testing

Tested on QEMU/x86_64: set, get and stats work on 172.44.0.2:11211.

scripts/test/ runs the checks automatically: wrapper.sh polls the port until
Memcached accepts connections (30s timeout) instead of sleeping a fixed interval, and
all.sh skips the Firecracker run when /dev/kvm is not writable rather than failing.

The Firecracker scripts are included but not fully verified: the test VM has no
/dev/kvm, and my local CPU hits Unikraft/Firecracker issues unrelated to this app.

@andreea110
andreea110 force-pushed the add-bincompat-memcached branch 4 times, most recently from 9485d32 to 8ed6343 Compare July 9, 2026 14:25
@andreea110 andreea110 changed the title bincompat-memcached: add initial rootfs Makefile and setup.sh bincompat-memcached Jul 10, 2026
@andreea110
andreea110 force-pushed the add-bincompat-memcached branch from 349ac0c to c7d533f Compare July 11, 2026 08:39
Apps that use threads fail with "Unsupported clone flags requested".
pthread_create() asks for the CLONE_SYSVSEM and CLONE_CHILD_CLEARTID
flags, but the handlers for them come from uklock semaphores and from
posix-futex, and LIBPOSIX_FUTEX is not enabled by anything.

Enable it in the QEMU and Firecracker defconfigs. It also selects
LIBUKLOCK, whose semaphores handle CLONE_SYSVSEM. The futex syscall
is needed by pthreads anyway.

With this change memcached can start its worker threads.

Signed-off-by: Andreea-Ștefania DUMITRACHE <dumitracheandreea155@gmail.com>
memcached needs eventfd2() for its worker threads. Without it the
syscall returns ENOSYS and memcached exits at startup.

Signed-off-by: Andreea-Ștefania DUMITRACHE <dumitracheandreea155@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new bincompat-memcached application that runs the system Memcached (1.6) as a Linux ELF under Unikraft’s binary-compatibility layer, using elfloader-net as the base and providing build/run/test automation for QEMU and Firecracker.

Changes:

  • Enable futex + eventfd support in elfloader-net defconfigs to support Memcached threading requirements.
  • Add bincompat-memcached rootfs build that bundles /usr/bin/memcached, required shared libraries, dynamic loader, and minimal passwd/group.
  • Add build/run/test scripts (including a Firecracker config) plus companion documentation for running and testing.

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
elfloader-net/scripts/defconfig/qemu.x86_64 Enables additional POSIX features (futex/eventfd) needed by Memcached.
elfloader-net/scripts/defconfig/fc.x86_64 Enables additional POSIX features (futex/eventfd) needed by Memcached.
bincompat-memcached/setup.sh Creates workdir/ layout and links required repos (modeled on other bincompat apps).
bincompat-memcached/scripts/test/wrapper.sh Starts an instance and validates Memcached set/get behavior.
bincompat-memcached/scripts/test/README.md Documents how to run the test scripts.
bincompat-memcached/scripts/test/common.sh Shared test helpers for starting/stopping instances and probing services.
bincompat-memcached/scripts/test/all.sh Builds and runs QEMU/FC test flows, capturing logs.
bincompat-memcached/scripts/test/.gitignore Ignores test log output directory.
bincompat-memcached/scripts/run/qemu.x86_64 QEMU run wrapper configuring networking and boot args for memcached.
bincompat-memcached/scripts/run/fc.x86_64 Firecracker run wrapper configuring tap networking and VM config.
bincompat-memcached/scripts/README.md Documents build/run/test script entrypoints.
bincompat-memcached/scripts/common.sh Shared build helpers; builds the elfloader-net base for the chosen target.
bincompat-memcached/scripts/build/rootfs.x86_64 Builds the rootfs and packs it into initrd.cpio.
bincompat-memcached/scripts/build/qemu.x86_64 Builds rootfs + QEMU kernel.
bincompat-memcached/scripts/build/kernel.qemu.x86_64 Builds the elfloader-net base kernel for QEMU.
bincompat-memcached/scripts/build/kernel.fc.x86_64 Builds the elfloader-net base kernel for Firecracker.
bincompat-memcached/scripts/build/fc.x86_64 Builds rootfs + Firecracker kernel.
bincompat-memcached/rootfs/Makefile Copies system memcached + shared libs and generates minimal /etc/passwd and /etc/group.
bincompat-memcached/rootfs/.gitignore Ignores generated rootfs artifacts.
bincompat-memcached/README.md Main app documentation for setup, build, run, and test.
bincompat-memcached/fc.x86_64.json Firecracker VM configuration (boot args, initrd, networking).
bincompat-memcached/.gitignore Ignores workdir/ and generated initrd.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread elfloader-net/scripts/defconfig/qemu.x86_64 Outdated
Comment thread elfloader-net/scripts/defconfig/fc.x86_64 Outdated
Comment thread bincompat-memcached/scripts/test/common.sh Outdated
Comment thread bincompat-memcached/scripts/test/common.sh
Comment thread bincompat-memcached/scripts/test/common.sh Outdated
Comment thread bincompat-memcached/scripts/test/all.sh Outdated
Comment thread bincompat-memcached/scripts/test/wrapper.sh Outdated
Comment thread bincompat-memcached/scripts/README.md Outdated
@razvand razvand self-assigned this Jul 11, 2026
@razvand razvand added the enhancement New feature or request label Jul 11, 2026
@andreea110
andreea110 force-pushed the add-bincompat-memcached branch from 3ffee83 to 6a03a93 Compare July 11, 2026 12:38
@andreea110
andreea110 marked this pull request as ready for review July 11, 2026 14:16
@razvand
razvand requested a review from Copilot July 11, 2026 19:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 22 changed files in this pull request and generated 3 comments.

Comment thread bincompat-memcached/scripts/test/common.sh Outdated
Comment thread bincompat-memcached/scripts/test/all.sh Outdated
Comment thread bincompat-memcached/rootfs/Makefile Outdated

@razvand razvand left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rootfs/ directory must contain a Dockerfile and a Makefile that builds and extracts the required root filesystem. The Dockerfile should be actually the one from the examples/memcached1.6-base/ directory in the unikraft/catalog repository.

The Makefile would run the docker and extract the root filesystem. The Makefile here is a good starting point.

The current way to do a Makefile relies on local filesystem files that may or may not be present. The Dockerfile is the best way for that.

@andreea110
andreea110 force-pushed the add-bincompat-memcached branch 2 times, most recently from 1c16087 to bd920fd Compare July 12, 2026 13:09
@razvand
razvand requested review from razvand and a lite review from Copilot August 21, 2026 08:22

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 25 out of 25 changed files in this pull request and generated no new comments.

Suppressed comments (17)

bincompat-memcached/README.md:10

  • The host memcached package is not used—the binary is taken from Docker—while every scripted test and the documented client command require nc, which is not in the top-level requirements and is not installed by apt install memcached on a minimal system. A clean setup can therefore reach nc: not found; document/install netcat-openbsd instead.
Make sure you installed the [requirements](../README.md#requirements), including `memcached` itself:

```console
sudo apt install memcached
**bincompat-memcached/rootfs/Dockerfile:35**
* Copying `/etc/passwd` alone is insufficient for the glibc `getpwnam()` lookup used by `-u root`: glibc resolves passwd entries through NSS and dynamically loads `libnss_files.so.2` (with the relevant NSS configuration). This scratch rootfs does not include that module, so Memcached can fail its user lookup at startup. Include the required NSS module/configuration, or change the launch strategy to avoid a name-based user lookup.

COPY --from=build /etc/passwd /etc/passwd

**bincompat-memcached/rootfs/Dockerfile:1**
* This image is intended to supply an x86_64 ELF, but the build stage follows the Docker host platform. On an arm64 build host, the stage contains arm64 paths/binaries while the later `COPY` commands require `/lib/x86_64-linux-gnu/...`, so the rootfs build fails instead of producing the documented target. Pin the build stage to `linux/amd64` (as the other binary-compatible Docker image does).

FROM memcached:1.6.23-bookworm as build

**bincompat-memcached/rootfs/Makefile:11**
* The `docker export | tar` pipeline reports only the `tar` status, and the following `docker rm` can mask either failure. A failed export or extraction can therefore make `make` succeed and leave an unusable rootfs. Check each step explicitly (and clean the temporary archive/container on failure).
docker export temp-container | tar -x -C $(ROOTFS_DIR)
docker rm temp-container
**bincompat-memcached/scripts/test/all.sh:31**
* The return status from this QEMU test, and from the Firecracker test below, is discarded. If QEMU fails and Firecracker succeeds, or if KVM is unavailable and the final `printf` runs, `all.sh` exits successfully despite a failed test. Accumulate the statuses and exit nonzero after all requested tests finish.

test_build_run qemu.x86_64

**bincompat-memcached/scripts/test/all.sh:29**
* `./setup.sh` is allowed to fail and the test suite continues with whatever repositories or artifacts happen to exist. That can make a setup failure look like a later test result (and, with stale builds, a false pass). Check this command and abort or propagate its status before starting builds.

./setup.sh

**bincompat-memcached/rootfs/Dockerfile:26**
* The comment contains a spelling error: `libraryes` should be `libraries`.

System libraryes

**bincompat-memcached/rootfs/Makefile:11**
* The fixed `temp-container` name is not cleaned up if an export is interrupted or a later recipe step fails, so the next build can fail at `docker create` with a name-conflict error; `make clean` does not remove Docker containers. Remove any stale container before creating it and install an exit trap to remove the current one.
docker create --name temp-container $(DOCKER_IMAGE) /usr/bin/memcached
mkdir -p $(ROOTFS_DIR)
docker export temp-container | tar -x -C $(ROOTFS_DIR)
docker rm temp-container
**bincompat-memcached/scripts/build/fc.x86_64:4**
* These commands are not chained, so a failed rootfs build/packaging step is followed by a kernel build and the latter's success status makes this script report success even though `initrd.cpio` is invalid or missing. Chain the commands (or enable fail-fast handling) so the kernel build is not reported as successful after a rootfs failure.

./scripts/build/rootfs.x86_64
./scripts/build/kernel.fc.x86_64

**bincompat-memcached/scripts/build/qemu.x86_64:3**
* These commands are not chained, so a failed rootfs build/packaging step is followed by a kernel build and the latter's success status makes this script report success even though `initrd.cpio` is invalid or missing. Chain the commands (or enable fail-fast handling) so the kernel build is not reported as successful after a rootfs failure.

./scripts/build/rootfs.x86_64
./scripts/build/kernel.qemu.x86_64

**bincompat-memcached/scripts/build/rootfs.x86_64:1**
* These commands are not fail-fast: a failed Docker build or extraction can be followed by `mkcpio`, and the script may then return success to the kernel build wrapper with an incomplete or missing initrd. Enable `set -e` (or chain the commands) so rootfs failures are propagated.

make -C rootfs/ clean
make -C rootfs/

**bincompat-memcached/scripts/run/fc.x86_64:20**
* This cleanup unconditionally downs and deletes the shared `tap0` name before recreating it. If another Firecracker VM or network service owns that interface, running this script can disconnect it. Use an application-specific interface or only delete a tap created by this script.

sudo ip link set dev virbr0 down
sudo ip link del dev virbr0
sudo ip link set dev tap0 down
sudo ip link del dev tap0

**bincompat-memcached/scripts/run/qemu.x86_64:20**
* This cleanup unconditionally downs and deletes `virbr0`, a common libvirt bridge name, before recreating it. On a host using libvirt or another VM on that bridge, running this script can disconnect and remove unrelated networking. Use an application-specific bridge or only remove an interface created by this script.

sudo ip link set dev virbr0 down
sudo ip link del dev virbr0
sudo ip link set dev tap0 down
sudo ip link del dev tap0

**bincompat-memcached/scripts/test/all.sh:11**
* This failure branch prints `FAILED` but then returns the status of `echo`, which is zero. As a result, callers cannot detect a failed Firecracker build when KVM is unavailable. Return nonzero from the failure branch so the test driver can propagate it.

This issue also appears on line 31 of the same file.
if test $? -eq 0; then
    echo "PASSED"
else
    echo "FAILED"
fi
**bincompat-memcached/scripts/test/common.sh:12**
* `fc.x86_64.json` is a shared basename used by many other applications in this repository (for example `c-hello` and `elfloader-net`). Matching only `firecracker.*fc.x86_64.json` can therefore SIGKILL an unrelated Firecracker VM whenever this test cleans up. Use a per-application socket or config path and match that unique identifier instead.
sudo pkill -9 -f "firecracker.*fc.x86_64.json"
**bincompat-memcached/scripts/test/common.sh:18**
* The test cleanup also unconditionally deletes `virbr0` after the test, so it can remove a pre-existing libvirt bridge or disconnect unrelated VMs even when this test did not create that interface. Restrict cleanup to interfaces owned by this test instead of deleting the shared name.
sudo ip link set dev virbr0 down
sudo ip link del dev virbr0
**bincompat-memcached/scripts/test/wrapper.sh:18**
* The test scripts invoke `nc` for readiness and protocol checks, but the application setup only tells users to install `memcached` and the repository requirements do not list netcat. On a clean supported host, `all.sh` will fail with `nc: not found`; document or install a concrete provider such as `netcat-openbsd`.

while ! nc -z -w 1 172.44.0.2 11211 2> /dev/null; do

</details>

Run the unmodified Linux Memcached 1.6 binary on Unikraft through
app-elfloader, with networking, on QEMU and Firecracker. The layout
follows bincompat-c-hello, with elfloader-net as the base kernel.

The rootfs is built from the system Memcached binary (apt) together
with its dynamic libraries and minimal /etc/passwd and /etc/group
files, needed because Memcached runs with "-u root" and looks up
the user with getpwnam(). The tests follow the structure from unikraft#112.

Signed-off-by: Andreea-Ștefania DUMITRACHE <dumitracheandreea155@gmail.com>
Signed-off-by: Andreea-Ștefania DUMITRACHE <dumitracheandreea155@gmail.com>
@andreea110
andreea110 force-pushed the add-bincompat-memcached branch from bd920fd to 013f7aa Compare August 21, 2026 09:17

@razvand razvand left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed-by: Razvan Deaconescu razvand@unikraft.io
Approved-by: Razvan Deaconescu razvand@unikraft.io

@razvand
razvand merged commit 5872ad0 into unikraft:scripts Aug 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants