Improve FREEd PID1
authorMathieu Baudier <mbaudier@argeo.org>
Sat, 9 Dec 2023 08:40:46 +0000 (09:40 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Sat, 9 Dec 2023 08:40:46 +0000 (09:40 +0100)
etc/freed/pid1/config.ini
local.mk
sjbin/src/freed-pid1.java

index ecc95023156b25191fe1fd632d584fb93ba9beda..3ed0e861a897dc1808d0b95b05f2b4ee522e5168 100644 (file)
@@ -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:///?\
index 531f8ab815cedb3651c8fabec424716a8e03f627..c97b72e8a851dac8e70455d90c905afe9ebcc2cd 100644 (file)
--- 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
index 0239cb755f22690cf1271d5d5ca641e32f9dc863..9dd1c313714d6f9f0fb8f679d3bb04e1b3aa59c1 100644 (file)
@@ -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<NetworkInterface> 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();
+       }
+
 }