diff --git a/DEVLOG.md b/DEVLOG.md index 2e95b36..a7426ca 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -1,6 +1,6 @@ # Tux-Dock Development Log -## 0.2-beta +## 0.3-beta This release introduces `tuxreaperd`, a micro init system for containers. diff --git a/README.md b/README.md index 752202b..1c2a6cb 100644 --- a/README.md +++ b/README.md @@ -52,9 +52,12 @@ sudo ./build/tux-dock # Override the report server port ./compile.sh --web-test-view 9000 + +# Force the libc-based tuxreaperd implementation +./compile.sh --force-libc-reaper ``` -`compile.sh` builds the `tuxreaperd` micro init before the main project. On supported hosts (`x86_64`/`amd64`/`aarch64`/`arm64`) it first tries the freestanding syscall implementation in `tuxreaperdasm.c`; on other architectures, or if the freestanding build fails, it falls back to the standard POSIX implementation in `tuxreaperdgnu.c`. +`compile.sh` builds the `tuxreaperd` micro init before the main project. On supported hosts (`x86_64`/`amd64`/`aarch64`/`arm64`) it first tries the freestanding syscall implementation in `tuxreaperdasm.c`; on other architectures, or if the freestanding build fails, it falls back to the standard POSIX implementation in `tuxreaperdgnu.c`. Pass `--force-libc-reaper` to skip the freestanding build and use the libc implementation directly. The web report is generated under `/tmp` and includes exact CTest output, test summaries, Docker integration output, a text rendition of the TUI flow, and the tuxreaperd zombie-reaping results. It requires `nc`, `netcat`, or Nmap's `ncat`; press `Ctrl-C` to stop the server. The default port is `8095`; pass a port after `--web-test-view` to override it. `--web-test-view --no-test` is invalid. Normal test runs include a Docker integration test using `debian:forky`, so Docker must be available. On systems with 1 GB or less of available memory, the script automatically uses a smaller build configuration and a single build job. @@ -122,7 +125,7 @@ ctest --test-dir build --output-on-failure ## About / Version -- Version: `0.2-beta` +- Version: `0.3-beta` - Created by: `markmental` - GitHub: https://github.com/MARKMENTAL/tuxdock - Forgejo: https://mentalnet.xyz/forgejo-v2/markmental/tuxdock diff --git a/compile.sh b/compile.sh index 79163b9..d4d484f 100755 --- a/compile.sh +++ b/compile.sh @@ -5,6 +5,7 @@ set -eu run_tests=1 web_view=0 web_port=8095 +force_libc_reaper=0 memory_limit=$(cat /sys/fs/cgroup/memory.max 2>/dev/null || true) if [ -z "$memory_limit" ] || [ "$memory_limit" = max ]; then @@ -44,8 +45,9 @@ while [ "$#" -gt 0 ]; do shift fi ;; + --force-libc-reaper) force_libc_reaper=1 ;; *) - printf '%s\n' "Usage: $0 [--no-test] [--web-test-view [port]]" >&2 + printf '%s\n' "Usage: $0 [--no-test] [--web-test-view [port]] [--force-libc-reaper]" >&2 exit 2 ;; esac @@ -81,18 +83,24 @@ command -v gcc >/dev/null 2>&1 || { host_arch=$(uname -m) asm_archs='x86_64 amd64 aarch64 arm64' +page_size=$(getconf PAGE_SIZE 2>/dev/null || printf '%s\n' 4096) build_tuxreaperd() { case " $asm_archs " in *" $host_arch "*) - printf '%s\n' "[compile] Building freestanding tuxreaperd for $host_arch" - if gcc -nostdlib -static -fno-stack-protector -fno-asynchronous-unwind-tables \ - -fno-builtin -O2 -s -Wl,--build-id=none -Wl,-z,noseparate-code \ - -Wall -Wextra tuxreaperdasm.c -o build/tuxreaperd 2>/tmp/tuxreaperd-asm-build.log; then - printf '%s\n' "[compile] Freestanding tuxreaperd built successfully" - return 0 + if [ "$force_libc_reaper" -eq 0 ]; then + printf '%s\n' "[compile] Building freestanding tuxreaperd for $host_arch" + if gcc -nostdlib -static -fno-stack-protector -fno-asynchronous-unwind-tables \ + -fno-builtin -O2 -s -Wl,--build-id=none -Wl,-z,noseparate-code \ + -Wl,-z,max-page-size=${page_size} \ + -Wall -Wextra tuxreaperdasm.c -o build/tuxreaperd 2>/tmp/tuxreaperd-asm-build.log; then + printf '%s\n' "[compile] Freestanding tuxreaperd built successfully" + return 0 + fi + printf '%s\n' "[compile] Freestanding build failed, falling back to libc implementation" >&2 + cat /tmp/tuxreaperd-asm-build.log >&2 + else + printf '%s\n' "[compile] --force-libc-reaper set, building libc tuxreaperd" fi - printf '%s\n' "[compile] Freestanding build failed, falling back to libc implementation" >&2 - cat /tmp/tuxreaperd-asm-build.log >&2 ;; esac diff --git a/tuxreaperdgnu.c b/tuxreaperdgnu.c index 9474474..1f8b715 100644 --- a/tuxreaperdgnu.c +++ b/tuxreaperdgnu.c @@ -59,6 +59,15 @@ int main(int argc, char *argv[]) { sa_chld.sa_flags = SA_RESTART | SA_NOCLDSTOP; sigaction(SIGCHLD, &sa_chld, NULL); + // Block the signals we wait on so the check/suspend loop is race-free + sigset_t block_mask, old_mask; + sigemptyset(&block_mask); + sigaddset(&block_mask, SIGCHLD); + sigaddset(&block_mask, SIGTERM); + sigaddset(&block_mask, SIGINT); + sigaddset(&block_mask, SIGHUP); + sigprocmask(SIG_BLOCK, &block_mask, &old_mask); + // Spawn the primary workload g_main_child = fork(); if (g_main_child < 0) { @@ -67,6 +76,7 @@ int main(int argc, char *argv[]) { } if (g_main_child == 0) { + sigprocmask(SIG_SETMASK, &old_mask, NULL); execvp(argv[1], &argv[1]); perror("execvp"); _exit(127); @@ -74,7 +84,7 @@ int main(int argc, char *argv[]) { // Block until the primary process exits while (!g_child_exited) { - pause(); + sigsuspend(&old_mask); } // Final sweep of any remaining lingering zombies