import java.time.Duration; import java.util.concurrent.TimeUnit; /** Source-launcher startup probe; uses the service's configured DOCKER_HOST. */ class WaitForDocker { /** * Waits for the configured Docker daemon before allowing the runner service to start. * * @param args optional timeout in seconds, from 1 through 300; defaults to 120 * @throws Exception if the timeout is invalid or the Docker probe cannot run * @implNote Exits nonzero if Docker does not become ready before the deadline. */ public static void main(final String... args) throws Exception { long seconds = args.length == 0 ? 120 : Long.parseLong(args[0]); if (seconds < 1 || seconds > 300) throw new IllegalArgumentException("Timeout must be 1–300 seconds"); long deadline = System.nanoTime() + Duration.ofSeconds(seconds).toNanos(); IO.println("Waiting for the configured Docker engine..."); while (System.nanoTime() < deadline) { Process process = new ProcessBuilder("docker", "info", "--format", "{{.ServerVersion}}") .redirectOutput(ProcessBuilder.Redirect.DISCARD) .redirectError(ProcessBuilder.Redirect.DISCARD) .start(); try { long remaining = Math.max(1, deadline - System.nanoTime()); if (process.waitFor(Math.min(remaining, TimeUnit.SECONDS.toNanos(5)), TimeUnit.NANOSECONDS) && process.exitValue() == 0) { IO.println("Docker is available; starting the Gitea runner."); return; } } finally { if (process.isAlive()) { process.destroyForcibly(); process.waitFor(); } } long remaining = deadline - System.nanoTime(); if (remaining > 0) TimeUnit.NANOSECONDS.sleep(Math.min(remaining, TimeUnit.SECONDS.toNanos(2))); } System.err.println("Docker did not become available within " + seconds + " seconds; runner not started."); System.exit(1); } }