From 29da175ca5498b8b5239535bb56b0bad61e96142 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sat, 9 Dec 2023 09:40:46 +0100 Subject: [PATCH] Improve FREEd PID1 --- etc/freed/pid1/config.ini | 4 +- local.mk | 4 +- sjbin/src/freed-pid1.java | 161 ++++++++++++++++++++++++++------------ 3 files changed, 115 insertions(+), 54 deletions(-) diff --git a/etc/freed/pid1/config.ini b/etc/freed/pid1/config.ini index ecc9502..3ed0e86 100644 --- a/etc/freed/pid1/config.ini +++ b/etc/freed/pid1/config.ini @@ -18,8 +18,8 @@ org.argeo.cms.lib.equinox,\ org.argeo.cms.lib.jetty,\ org.argeo.cms.jshell,\ -argeo.http.port=8080 -#argeo.sshd.port=22 +#argeo.http.port=80 +argeo.sshd.port=22 argeo.osgi.sources=\ a2:///?\ diff --git a/local.mk b/local.mk index 531f8ab..c97b72e 100644 --- a/local.mk +++ b/local.mk @@ -5,7 +5,7 @@ bindir ?= $(exec_prefix)/bin sbindir ?= $(exec_prefix)/sbin libdir ?= $(exec_prefix)/lib libexecdir ?= $(exec_prefix)/libexec -sysconfdir = $(prefix)/etc +sysconfdir ?= $(prefix)/etc srcdir ?= src datarootdir ?= $(prefix)/share @@ -22,5 +22,5 @@ install: $(COPY) -r usr/bin/* $(DESTDIR)$(bindir) $(COPY) -r usr/share/* $(DESTDIR)$(datarootdir) $(COPY) -r usr/lib/* $(DESTDIR)$(libdir) - $(COPY) -r usr/libexec/* $(DESTDIR)$(libexec) + $(COPY) -r usr/libexec/* $(DESTDIR)$(libexecdir) $(MAKE) -C sjbin install diff --git a/sjbin/src/freed-pid1.java b/sjbin/src/freed-pid1.java index 0239cb7..9dd1c31 100644 --- a/sjbin/src/freed-pid1.java +++ b/sjbin/src/freed-pid1.java @@ -2,9 +2,14 @@ import java.io.IOException; import java.lang.management.ManagementFactory; +import java.net.InetAddress; +import java.net.InterfaceAddress; +import java.net.NetworkInterface; +import java.net.SocketException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Enumeration; import java.util.TreeMap; import org.argeo.init.Service; @@ -14,59 +19,73 @@ import sun.misc.Signal; class FreedPid1 { public static void main(String... args) { - final long pid = ProcessHandle.current().pid(); - System.out.println("FREEd Init daemon starting with pid " + pid + "..."); + try { + final long pid = ProcessHandle.current().pid(); + System.out.println("FREEd Init daemon starting with pid " + pid + "..."); // System.out.println(System.getProperty("user.dir")); // System.out.println(System.getProperty("user.name")); // System.out.println(System.getProperty("user.home")); - // System.setProperty("user.dir", "/tmp"); - for (Object key : new TreeMap<>(System.getProperties()).keySet()) { - System.out.println(key + "=" + System.getProperty(key.toString())); - } + // System.setProperty("user.dir", "/tmp"); + for (Object key : new TreeMap<>(System.getProperties()).keySet()) { + System.out.println(key + "=" + System.getProperty(key.toString())); + } - System.out.flush(); + flushStd(); - Signal.handle(new Signal("TERM"), (signal) -> { - System.out.println("SIGTERM caught"); - System.exit(0); - }); - Signal.handle(new Signal("INT"), (signal) -> { - System.out.println("SIGINT caught"); - System.exit(0); - }); - Signal.handle(new Signal("HUP"), (signal) -> { - System.out.println("SIGHUP caught"); - System.exit(0); - }); - - if (args.length > 0 && ("1".equals(args[0]) // - || "single".equals(args[0]) // - || "emergency".equals(args[0]))) { - // TODO check if we can remove dependency to management - String classpath = ManagementFactory.getRuntimeMXBean().getClassPath(); - String feedbackMode = "concise"; - // TODO --startup script - JavaShellToolBuilder builder = JavaShellToolBuilder.builder(); - try { - builder.start("--execution", "direct", "--class-path", classpath, "--feedback", feedbackMode); - } catch (Exception e) { - e.printStackTrace(); - System.err.flush(); - System.exit(1); - return; - } + Signal.handle(new Signal("TERM"), (signal) -> { + System.out.println("SIGTERM caught"); + System.exit(0); + }); + Signal.handle(new Signal("INT"), (signal) -> { + System.out.println("SIGINT caught"); + System.exit(0); + }); + Signal.handle(new Signal("HUP"), (signal) -> { + System.out.println("SIGHUP caught"); + System.exit(0); + }); - } else { - // init Linux services - initSysctl(); - startInitDService("networking"); - startInitDService("nslcd"); + if (args.length > 0 && ("1".equals(args[0]) // + || "single".equals(args[0]) // + || "emergency".equals(args[0]))) { + // TODO check if we can remove dependency to management + String classpath = ManagementFactory.getRuntimeMXBean().getClassPath(); + String feedbackMode = "concise"; + // TODO --startup script + JavaShellToolBuilder builder = JavaShellToolBuilder.builder(); + try { + builder.start("--execution", "direct", "--class-path", classpath, "--feedback", feedbackMode); + } catch (Exception e) { + e.printStackTrace(); + System.err.flush(); + System.exit(1); + return; + } - waitForNetwork(); + } else { + // init Linux services + initSysctl(); + startInitDService("networking"); + flushStd(); + + if (!waitForNetwork(30 * 1000)) { + System.err.println("No network available"); + } + flushStd(); - // init Argeo CMS - Service.main(args); + startInitDService("nslcd"); + + // init Argeo CMS + Service.main(args); + } + } catch (Throwable e) { + System.err.println("Unexpected exception in free-pid1 init, shutting down... " + e.getMessage()); + e.printStackTrace(); + flushStd(); + System.exit(1); +// if(e instanceof Error) +// throw e; } } @@ -105,12 +124,54 @@ class FreedPid1 { System.out.println("Service " + serviceName + " not found and therefore not started"); } - static void waitForNetwork() { - // TODO Do it properly - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); + static boolean waitForNetwork(long timeout) { + long begin = System.currentTimeMillis(); + long duration = 0; + boolean networkAvailable = false; + networkAvailable: while (!networkAvailable) { + duration = System.currentTimeMillis() - begin; + if (duration > timeout) + break networkAvailable; + Enumeration netInterfaces = null; + try { + netInterfaces = NetworkInterface.getNetworkInterfaces(); + } catch (SocketException e) { + throw new IllegalStateException("Cannot list network interfaces", e); + } + if (netInterfaces != null) { + while (netInterfaces.hasMoreElements()) { + NetworkInterface netInterface = netInterfaces.nextElement(); + for (InterfaceAddress addr : netInterface.getInterfaceAddresses()) { + InetAddress inetAddr = addr.getAddress(); + if (!inetAddr.isLoopbackAddress() && !inetAddr.isLinkLocalAddress()) { + try { + if (inetAddr.isReachable((int) timeout)) { + networkAvailable = true; + System.out.println("Network available after " + duration + " ms. IP: " + inetAddr); + break networkAvailable; + } + } catch (IOException e) { + System.err.println( + "Cannot check whether " + inetAddr + " is reachable: " + e.getMessage()); + } + } + } + } + } else { + throw new IllegalStateException("No network interface has been found"); + } + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } } + return networkAvailable; } + + static void flushStd() { + System.err.flush(); + System.out.flush(); + } + } -- 2.30.2