tuxdock/DEVLOG.md
2026-08-30 10:55:34 -04:00

7.7 KiB

Tux-Dock Development Log

0.4.1-beta

TUI stability

  • Fixed duplicate port mappings shown in the container list TUI. Docker's /containers/json API returns separate Ports entries for IPv4 (0.0.0.0) and IPv6 (::) bindings of the same host port; the container parser now deduplicates these into a single public:private display string.
  • Added a container parser regression test covering IPv4/IPv6 duplicate port bindings.
  • Added DockerStatePoller, a background thread that silently refreshes cached container/image state from Docker every 5 seconds. This prevents state drift when an Engine API call times out but Docker still applied the change.
  • Made mutating Engine API operations idempotent: removeContainer treats 404 as success, deleteImage treats 404 as success, and startDetached treats 304 as success, eliminating spurious "already removed/started" failures on retry.
  • Refactored DockerManager to accept an injectable DockerEngineClient for unit testing.
  • Added unit tests for idempotent Docker manager operations and for DockerStatePoller lifecycle, periodic polling, and immediate refresh triggers.

Version

  • Bumped version to 0.4.1-beta.

0.4-beta

ARM64 / tuxreaperd fixes

  • Fixed tuxreaperdasm.c on ARM64 by using the architecture-specific O_DIRECTORY value (0x4000 on aarch64, 0x10000 on x86_64). The hardcoded x86_64 value caused openat("/proc", ...) to fail with EINVAL, which broke /proc scanning, descendant waiting, and SIGTERM forwarding on ARM64 Chromebooks/VMs.
  • Verified graceful Apache shutdown on ARM64: tuxreaperd remaps SIGTERM to SIGWINCH for Apache processes and waits for descendants to finish, allowing in-flight HTTP responses to complete before the container exits.
  • Added nginx-aware SIGTERM→SIGQUIT remapping in both tuxreaperdgnu.c and tuxreaperdasm.c. When docker stop sends SIGTERM, nginx processes (/usr/sbin/nginx, /usr/local/nginx/sbin/nginx) receive SIGQUIT for graceful shutdown instead of SIGTERM.
  • Added PHP-FPM-aware SIGTERM→SIGQUIT remapping with prefix matching (e.g., /usr/sbin/php-fpm matches /usr/sbin/php-fpm8.4) so PHP-FPM receives the correct graceful-shutdown signal when the container stops.
  • Documented that PHP-FPM graceful shutdown requires process_control_timeout to be set in the PHP-FPM pool configuration (e.g., process_control_timeout = 60s). Without it, the PHP-FPM master exits immediately on SIGQUIT and in-flight requests are dropped.
  • Set the container stop timeout to 60 seconds in DockerManager::createContainer (--stop-timeout=60) and raised the TUI stop default to 60 seconds, aligning Docker's grace period with tuxreaperd's descendant wait so graceful shutdowns are not cut short by a premature SIGKILL.
  • Added --debug-reaper flag to compile.sh to build tuxreaperd with TUXREAPERD_DEBUG and run verbose tests; useful for diagnosing /proc scanning, signal broadcasts, and descendant waits.
  • Added adaptive TTY/non-TTY spinner to compile.sh for clearer feedback during the test phase.
  • Added a "Why tuxreaperd?" comparison section to README.md with a feature matrix and ASCII size chart contrasting tuxreaperd with tini, dumb-init, and mini-init-asm.
  • Added a "Web workload guide" section to README.md covering Apache, nginx, and PHP-FPM signal conventions, required PHP-FPM process_control_timeout configuration, container startup examples, and the sleep.php verification test.

Version

  • Bumped version to 0.4-beta.

0.3.1-beta

Added an optional timeout_seconds parameter to stopContainer

0.3-beta

This release introduces tuxreaperd, a micro init system for containers.

Micro init

  • Split the reaper into two implementations:
    • tuxreaperdgnu.c: the original standard POSIX/libc daemon used as PID 1 inside containers created by tux-dock.
    • tuxreaperdasm.c: a new freestanding -nostdlib syscall engine for x86_64 and aarch64 with a tiny static footprint.
  • Both run as subreapers (PR_SET_CHILD_SUBREAPER) with a SIGCHLD handler that reaps every reparented/terminated descendant, so orphaned processes never accumulate as zombies.
  • Both proxy lifecycle signals (SIGTERM, SIGQUIT, SIGINT, SIGHUP, SIGUSR1, SIGUSR2) to the child process tree and propagate the primary workload's exit status (128 + signal for signal deaths).
  • Special-cases Apache's questionable use of SIGWINCH for graceful shutdown: when SIGTERM is received, any process whose /proc/<pid>/exe is /usr/sbin/apache2, /usr/sbin/httpd, or /usr/local/apache2/bin/httpd gets SIGWINCH instead, while every other process receives SIGTERM.
  • compile.sh detects the host architecture and builds the freestanding implementation when possible, falling back to tuxreaperdgnu.c on failure or unsupported hosts.
  • DockerManager::createContainer bind-mounts tuxreaperd into the container as PID 1 and resolves the binary next to the tux-dock executable when it is not in the current directory.

Tests

  • Added tuxreaperd-zombie-tests, an in-container test suite that boots a container with tuxreaperd as PID 1 and verifies orphaned grandchildren are reaped (zero zombies), exit status is propagated, and docker stop cleanly shuts down via forwarded SIGTERM (exit 143).
  • The HTML web test view now includes a "Tuxreaperd Zombie Reaping" section alongside the Docker integration and TUI transcript sections.

0.1.2-beta

This release adds signal trapping to prevent state corruption during long-running Docker operations.

Reliability

  • Added SIGINT (Ctrl+C) signal trapping during busy operations to prevent premature exit and socket corruption
  • Added SIGTSTP (Ctrl+Z) signal trapping during busy operations to prevent suspension mid-operation
  • Signals chain to previous handlers when not busy, preserving normal exit and suspend behavior
  • Trap re-installs after terminal I/O restoration cycles to maintain protection through Attach Shell sessions
  • Used SA_RESTART flag to prevent EINTR on blocking socket reads during signal delivery

TUI

  • Added visual feedback in busy modal when signals are trapped
  • Shows "Ctrl+C ignored: operation in progress" when SIGINT is trapped
  • Shows "Ctrl+Z ignored: operation in progress" when SIGTSTP is trapped

0.1.1-beta

This release establishes the first beta-quality Docker integration and TUI workflow.

Docker integration

  • Added direct Docker Engine API access through /var/run/docker.sock.
  • Added startup Docker preflight using GET /_ping before launching the TUI.
  • Added synchronous initial container and image loading.
  • Added asynchronous cache refreshes after mutations and interactive sessions.
  • Preserved cached state when a refresh fails.
  • Added structured container/image JSON mapping with exited-container support.

Process execution

  • Replaced system() and popen() with a fork/exec process runner.
  • Added captured stdout/stderr and inherited terminal I/O modes.
  • Kept direct CLI execution for interactive terminal handoffs.

Reliability

  • Added HTTP response parsing for Content-Length, chunked transfer, and bodyless responses.
  • Added robust handling for Docker 204 and idempotent 304 responses.
  • Added tri-state stop polling: stopped, running, and unknown.
  • Added bounded stop retries after transport timeouts.
  • Stop completion now refreshes cached state before showing the result modal.

TUI

  • Replaced the persistent status panel with a centered actions panel.
  • Added busy-operation modals with spinner feedback.
  • Blocked input during long-running Docker operations.
  • Added structured, scrollable container and image list dialogs.

Tests

  • Added HTTP response parser tests.
  • Added container JSON mapping tests.
  • Added operation-state tests.
  • Added stop polling and timeout-sequence regression tests.