From 1d9964c6ad9d85aa5237b648a06de42901f68821 Mon Sep 17 00:00:00 2001 From: danbugs Date: Tue, 30 Jun 2026 22:45:52 +0000 Subject: [PATCH 1/4] fix(kernel): point kraft.yaml at unikraft idle-poll fix branch Signed-off-by: danbugs --- examples/networking-py/kraft.yaml | 4 ++-- examples/python-agent-driver/kraft.yaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/networking-py/kraft.yaml b/examples/networking-py/kraft.yaml index 67531a4..2abd305 100644 --- a/examples/networking-py/kraft.yaml +++ b/examples/networking-py/kraft.yaml @@ -2,8 +2,8 @@ specification: '0.6' name: networking-py-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: fix/net-poll-sleep kconfig: # Platform CONFIG_PLAT_HYPERLIGHT: 'y' diff --git a/examples/python-agent-driver/kraft.yaml b/examples/python-agent-driver/kraft.yaml index 425b327..318310a 100644 --- a/examples/python-agent-driver/kraft.yaml +++ b/examples/python-agent-driver/kraft.yaml @@ -2,8 +2,8 @@ specification: '0.6' name: python-agent-driver-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: fix/net-poll-sleep kconfig: CONFIG_PLAT_HYPERLIGHT: 'y' CONFIG_PAGING: 'n' From 127a26a074e774fc7ca2110fd08ca107b23b3993 Mon Sep 17 00:00:00 2001 From: danbugs Date: Tue, 30 Jun 2026 22:45:57 +0000 Subject: [PATCH 2/4] test: add urllib GET without timeout CI test Signed-off-by: danbugs --- .github/workflows/test-examples.yml | 6 +++++ examples/networking-py/Dockerfile | 1 + .../networking-py/urllib_get_no_timeout.py | 25 +++++++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 examples/networking-py/urllib_get_no_timeout.py diff --git a/.github/workflows/test-examples.yml b/.github/workflows/test-examples.yml index d372ee3..1b45e75 100644 --- a/.github/workflows/test-examples.yml +++ b/.github/workflows/test-examples.yml @@ -223,6 +223,9 @@ jobs: - example: networking-py args: "--net -- /urllib_get.py" expect: "SUCCESS: urllib GET worked!" + - example: networking-py + args: "--net -- /urllib_get_no_timeout.py" + expect: "SUCCESS: urllib GET \\(no timeout\\) worked!" - example: networking-py args: "--port 8080 -- /echo_server_test.py" expect: "SUCCESS: bind\\+listen on port 8080 allowed" @@ -613,6 +616,9 @@ jobs: - example: networking-py args: "--net -- /urllib_get.py" expect: "SUCCESS: urllib GET worked!" + - example: networking-py + args: "--net -- /urllib_get_no_timeout.py" + expect: "SUCCESS: urllib GET \\(no timeout\\) worked!" - example: networking-py args: "--port 8080 -- /echo_server_test.py" expect: "SUCCESS: bind\\+listen on port 8080 allowed" diff --git a/examples/networking-py/Dockerfile b/examples/networking-py/Dockerfile index c16ba5b..b550171 100644 --- a/examples/networking-py/Dockerfile +++ b/examples/networking-py/Dockerfile @@ -8,6 +8,7 @@ FROM ${BASE} AS rootfs COPY http_get.py /http_get.py COPY echo_server.py /echo_server.py COPY urllib_get.py /urllib_get.py +COPY urllib_get_no_timeout.py /urllib_get_no_timeout.py COPY https_test.py /https_test.py COPY echo_server_test.py /echo_server_test.py diff --git a/examples/networking-py/urllib_get_no_timeout.py b/examples/networking-py/urllib_get_no_timeout.py new file mode 100644 index 0000000..fe937a4 --- /dev/null +++ b/examples/networking-py/urllib_get_no_timeout.py @@ -0,0 +1,25 @@ +"""HTTP GET using urllib WITHOUT an explicit timeout. + +Same as urllib_get.py but omits the timeout= argument to urlopen(). +This exercises the code path used by mxc, where the Unikraft guest +kernel relies on the idle thread's halt_irq callback to poll sockets +via __hl_sleep rather than an explicit timeout-driven poll cycle. +""" +import urllib.request +import sys + +URL = "http://example.com/" + +print(f"Fetching {URL} (no timeout) ...") +try: + with urllib.request.urlopen(URL) as resp: + body = resp.read().decode("utf-8", errors="replace") + print(f"Status: {resp.status}") + print(f"Body length: {len(body)} bytes") + if "Example Domain" in body: + print("SUCCESS: urllib GET (no timeout) worked!") + else: + print("WARNING: unexpected body content") +except Exception as e: + print(f"FAILED: {e}") + sys.exit(1) From 06b6fbe47969e50cfd605ae0f70706328511fd5a Mon Sep 17 00:00:00 2001 From: danbugs Date: Fri, 3 Jul 2026 13:44:52 +0000 Subject: [PATCH 3/4] fix(kernel): point kraft.yaml at upstream unikraft plat-hyperlight Signed-off-by: danbugs --- examples/networking-py/kraft.yaml | 4 ++-- examples/python-agent-driver/kraft.yaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/networking-py/kraft.yaml b/examples/networking-py/kraft.yaml index 2abd305..67531a4 100644 --- a/examples/networking-py/kraft.yaml +++ b/examples/networking-py/kraft.yaml @@ -2,8 +2,8 @@ specification: '0.6' name: networking-py-hyperlight unikraft: - source: https://github.com/danbugs/unikraft.git - version: fix/net-poll-sleep + source: https://github.com/unikraft/unikraft.git + version: plat-hyperlight kconfig: # Platform CONFIG_PLAT_HYPERLIGHT: 'y' diff --git a/examples/python-agent-driver/kraft.yaml b/examples/python-agent-driver/kraft.yaml index 318310a..425b327 100644 --- a/examples/python-agent-driver/kraft.yaml +++ b/examples/python-agent-driver/kraft.yaml @@ -2,8 +2,8 @@ specification: '0.6' name: python-agent-driver-hyperlight unikraft: - source: https://github.com/danbugs/unikraft.git - version: fix/net-poll-sleep + source: https://github.com/unikraft/unikraft.git + version: plat-hyperlight kconfig: CONFIG_PLAT_HYPERLIGHT: 'y' CONFIG_PAGING: 'n' From 7bed20fff81c2438214926d698cd9b9744beb4bc Mon Sep 17 00:00:00 2001 From: danbugs Date: Fri, 3 Jul 2026 13:44:52 +0000 Subject: [PATCH 4/4] ci: add per-test timeout to Windows runtime tests Signed-off-by: danbugs --- .github/workflows/test-examples.yml | 33 ++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test-examples.yml b/.github/workflows/test-examples.yml index 1b45e75..8cb2fe4 100644 --- a/.github/workflows/test-examples.yml +++ b/.github/workflows/test-examples.yml @@ -759,16 +759,30 @@ jobs: } } + # Helper: run a command with a per-test timeout (seconds). + function Invoke-WithTimeout { + param([int]$Seconds, [string]$Exe, [string[]]$ArgList) + $outFile = Join-Path $env:RUNNER_TEMP 'hl-test-out.log' + $proc = Start-Process -FilePath $Exe -ArgumentList $ArgList ` + -NoNewWindow -RedirectStandardOutput $outFile -RedirectStandardError "$outFile.err" -PassThru + if (-not $proc.WaitForExit($Seconds * 1000)) { + Stop-Process -Id $proc.Id -Force -ErrorAction SilentlyContinue + Write-Host "FAIL: timed out after ${Seconds}s" + Get-Content $outFile -ErrorAction SilentlyContinue + exit 1 + } + $script:out = Get-Content $outFile -Raw -ErrorAction SilentlyContinue + $script:rc = $proc.ExitCode + } + switch ($driver) { 'multifn-test' { - $out = & multifn-test $kernel $cpio 2>&1 - $rc = $LASTEXITCODE + Invoke-WithTimeout -Seconds 60 -Exe 'multifn-test' -ArgList @($kernel, $cpio) } 'pydriver-run' { "print('hello from driver')" | Out-File -Encoding ascii tiny.py $tiny = (Resolve-Path "tiny.py").Path - $out = & pydriver-run $kernel $cpio $tiny 2>&1 - $rc = $LASTEXITCODE + Invoke-WithTimeout -Seconds 120 -Exe 'pydriver-run' -ArgList @($kernel, $cpio, $tiny) } default { $argList = @() @@ -779,16 +793,15 @@ jobs: if ($memory -ne '') { $memArgs = @('-m', $memory) } - $out = & hyperlight-unikraft -q @memArgs ` - $kernel --initrd $cpio @mountArgs @toolArgs @argList 2>&1 - $rc = $LASTEXITCODE + Invoke-WithTimeout -Seconds 120 -Exe 'hyperlight-unikraft' ` + -ArgList (@('-q') + $memArgs + @($kernel, '--initrd', $cpio) + $mountArgs + $toolArgs + $argList) } } - $outStr = ($out | Out-String) + if ($null -eq $out) { $out = '' } Write-Host "=== output (exit=$rc) ===" - Write-Host $outStr - if (-not ($outStr -match $expect)) { + Write-Host $out + if (-not ($out -match $expect)) { Write-Host "FAIL: did not match /$expect/" exit 1 }