feat: add Go and .NET Kestrel HTTP server examples - #97
Conversation
When networking is enabled, __hl_sleep now uses libc::poll() on all open host sockets instead of a plain sleep. This lets the guest's scheduler wake early when socket I/O is ready, enabling async networking with a single vCPU. Also adds net_poll hcall for non-blocking socket readiness checks. Signed-off-by: danbugs <danilochiarlone@gmail.com>
Minimal Go net/http server running on Hyperlight with host-proxied async networking via hostsock. Includes Dockerfile for cross-platform rootfs builds. Signed-off-by: danbugs <danilochiarlone@gmail.com>
ASP.NET Core Kestrel web server on Hyperlight using the same async networking infrastructure as go-http. Uses CreateEmptyBuilder to avoid inotify dependency (ENOSYS on Unikraft). Signed-off-by: danbugs <danilochiarlone@gmail.com>
HTTP server examples need a different test path: start the server in the background, poll until ready, curl the endpoint, check the response body, then kill the server. Signed-off-by: danbugs <danilochiarlone@gmail.com>
Signed-off-by: danbugs <danilochiarlone@gmail.com>
There was a problem hiding this comment.
Pull request overview
This PR extends Hyperlight-Unikraft’s host-side networking support to enable non-blocking socket readiness checks (and early wakeups during guest sleeps), and adds new HTTP server examples for Go and .NET (Kestrel), wiring both into CI build + runtime testing on Linux and Windows.
Changes:
- Add host-side socket polling during
__hl_sleepand introduce anet_polltool/hcall (Unix-only) for checking socket readiness. - Add new Go HTTP server example (
examples/go-http) including a Docker-built initrd and an ELF PT_INTERP patching helper. - Add new .NET Kestrel HTTP server example (
examples/dotnet-http) plus CI runtime test coverage for both new examples.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
host/src/lib.rs |
Adds socket-table plumbing, net_poll, and a __hl_sleep variant that polls sockets while sleeping. |
examples/go-http/patch_interp.py |
Helper script to patch PT_INTERP out of Go static PIE binaries for Unikraft elfloader compatibility. |
examples/go-http/main.go |
Simple net/http “Hello” server. |
examples/go-http/kraft.yaml |
Unikraft config to boot/run the Go server via elfloader. |
examples/go-http/Justfile |
Build/run/rootfs automation for the Go HTTP example. |
examples/go-http/Dockerfile |
Builds the Go server binary and produces a CPIO initrd. |
examples/dotnet-http/Program.cs |
Minimal Kestrel-based HTTP server using CreateEmptyBuilder. |
examples/dotnet-http/kraft.yaml |
Unikraft config to boot/run the .NET apphost via elfloader. |
examples/dotnet-http/KestrelHyperlight.csproj |
.NET project definition for the Kestrel example. |
examples/dotnet-http/Justfile |
Build/run/rootfs automation for the .NET HTTP example. |
examples/dotnet-http/Dockerfile |
Publishes a self-contained .NET app + runtime into a CPIO initrd. |
.github/workflows/test-examples.yml |
Adds build/runtime CI coverage for go-http and dotnet-http on Linux + Windows. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Linux Benchmarks
Details
| Benchmark suite | Current: f8d20d3 | Previous: c2092b3 | Ratio |
|---|---|---|---|
hello_world (median) |
20 ms |
20 ms |
1 |
pandas (median) |
110 ms |
110 ms |
1 |
density (per VM) |
11 MB |
11 MB |
1 |
snapshot (disk) |
656 MiB |
656 MiB |
1 |
This comment was automatically generated by workflow using github-action-benchmark.
Build with CGO_ENABLED=1 and -extldflags "-static-pie" instead of patching PT_INTERP out of CGO_ENABLED=0 PIE binaries. Signed-off-by: danbugs <danilochiarlone@gmail.com>
…erp.py" This reverts commit bd1e178. Signed-off-by: danbugs <danilochiarlone@gmail.com>
0b52e67 to
7e9881b
Compare
There was a problem hiding this comment.
Windows Benchmarks
Details
| Benchmark suite | Current: f8d20d3 | Previous: c2092b3 | Ratio |
|---|---|---|---|
hello_world (median) |
328 ms |
320 ms |
1.02 |
pandas (median) |
1034 ms |
887 ms |
1.17 |
density (per VM) |
656 MB |
656 MB |
1 |
snapshot (disk) |
664 MiB |
664 MiB |
1 |
This comment was automatically generated by workflow using github-action-benchmark.
Clamp timeout_ms before i64→c_int cast, validate events range, handle poll() errors and EINTR, report POLLNVAL for unknown fds, add argument check to patch_interp.py. Signed-off-by: danbugs <danilochiarlone@gmail.com>
Socket polling (hl_sleep_poll_sockets) is Unix-only, so HTTP server examples cannot serve requests on Windows. Remove them from package-images-for-windows and runtime-test-windows matrices. Signed-off-by: danbugs <danilochiarlone@gmail.com>
Implement hl_sleep_poll_sockets and handle_net_poll for Windows using WSAPoll from winsock2, matching the Unix libc::poll() implementations. This enables HTTP server examples (go-http, dotnet-http) to run on Windows by waking the guest when socket I/O arrives. Restores go-http and dotnet-http in Windows CI matrices. Signed-off-by: danbugs <danilochiarlone@gmail.com>
The guest sends POSIX poll flags (POLLIN=1, POLLOUT=4, POLLERR=8) but WSAPoll uses different values (POLLRDNORM=256, POLLWRNORM=16, POLLERR=1). Without translation, POSIX POLLIN was interpreted as Windows POLLERR, preventing connection readiness detection on Windows. Signed-off-by: danbugs <danilochiarlone@gmail.com>
Signed-off-by: danbugs <danilochiarlone@gmail.com>
Signed-off-by: danbugs <danilochiarlone@gmail.com>
The CI HTTP server tests (go-http, dotnet-http) were failing because Invoke-WebRequest -TimeoutSec 2 sent RST before the server could process the connection through the hostsock sleep-rescan cycle. Use 127.0.0.1 to avoid IPv6 resolution, increase per-request timeout to 10s, and add an initial delay for the unikernel to boot. Signed-off-by: danbugs <danilochiarlone@gmail.com>
Signed-off-by: danbugs <danilochiarlone@gmail.com>
Summary
__hl_sleepso the guest scheduler wakes early when network I/O is ready, enabling async networking with a single vCPUnet_pollhcall for non-blocking socket readiness checksexamples/go-http)examples/dotnet-http) usingCreateEmptyBuilderto avoid inotify dependency (ENOSYS on Unikraft)Depends on unikraft/unikraft#1852 for the hostsock readiness checks and event rescanning on the guest side.
Test plan