Author: toad
Date: 2006-06-21 16:48:37 +0000 (Wed, 21 Jun 2006)
New Revision: 9337

Modified:
   trunk/freenet/src/freenet/io/comm/UdpSocketManager.java
   trunk/freenet/src/freenet/node/Node.java
   trunk/freenet/src/freenet/node/Version.java
Log:
832: Auto-restart the node if the UdpSocketManager (packet receiver thread) 
hangs.

Modified: trunk/freenet/src/freenet/io/comm/UdpSocketManager.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/UdpSocketManager.java     2006-06-21 
16:27:27 UTC (rev 9336)
+++ trunk/freenet/src/freenet/io/comm/UdpSocketManager.java     2006-06-21 
16:48:37 UTC (rev 9337)
@@ -22,6 +22,9 @@
 import java.net.*;
 import java.util.*;

+import org.tanukisoftware.wrapper.WrapperManager;
+
+import freenet.node.Node;
 import freenet.node.PeerNode;
 import freenet.support.Logger;

@@ -44,11 +47,17 @@
        private boolean _isDone = false;
        private static UdpSocketManager _usm;
        private static final int MAX_UNMATCHED_FIFO_SIZE = 50000;
+       private volatile int lastTimeInSeconds;

-       protected UdpSocketManager() {
+       // Icky layer violation, but we need to know the Node to work around 
the EvilJVMBug.
+       private final Node node;
+       
+       protected UdpSocketManager(Node node) {
+               this.node = node;
        }

        public void start() {
+               lastTimeInSeconds = (int) (System.currentTimeMillis() / 1000);
                setDaemon(true);
                setPriority(Thread.MAX_PRIORITY);
                super.start();
@@ -66,9 +75,39 @@
                                } catch (InterruptedException e) {
                                        // Ignore
                                }
-                               if(UdpSocketManager.this.isAlive())
+                               if(UdpSocketManager.this.isAlive()) {
                                        Logger.minor(this, "PING on 
"+UdpSocketManager.this);
-                               else {
+                                       long time = System.currentTimeMillis();
+                                       int timeSecs = (int) (time / 1000);
+                                       if(timeSecs - lastTimeInSeconds > 3*60) 
{
+                                               
+                                               // USM has hung.
+                                               // Probably caused by the 
EvilJVMBug (see PacketSender).
+                                               // We'd better restart... :(
+                                               
+                                               
if(!Node.logConfigHandler.getFileLoggerHook().hasRedirectedStdOutErrNoLock())
+                                                       
System.err.println("Restarting node: UdpSocketManager froze for 3 minutes!");
+                                               
+                                               try {
+                                                       
if(node.isUsingWrapper()){
+                                                               
WrapperManager.requestThreadDump();
+                                                               
WrapperManager.restart();
+                                                       }else{
+                                                               
if(!Node.logConfigHandler.getFileLoggerHook().hasRedirectedStdOutErrNoLock())
+                                                                       
System.err.println("Exiting on deadlock, but not running in the wrapper! Please 
restart the node manually.");
+                                                               
+                                                               // No wrapper : 
we don't want to let it harm the network!
+                                                               node.exit();
+                                                       }
+                                               } catch (Throwable t) {
+                                                       
if(!Node.logConfigHandler.getFileLoggerHook().hasRedirectedStdOutErrNoLock()) {
+                                                               
System.err.println("Error : can't restart the node : consider installing the 
wrapper. PLEASE REPORT THAT ERROR TO devl at freenetproject.org");
+                                                               
t.printStackTrace();
+                                                       }
+                                                       node.exit();
+                                               }
+                                       }
+                               } else {
                                        Logger.error(this, "MAIN LOOP 
TERMINATED");
                                        System.err.println("MAIN LOOP 
TERMINATED!");
                                        
System.exit(freenet.node.Node.EXIT_MAIN_LOOP_LOST);
@@ -77,8 +116,9 @@
                }
        }

-       public UdpSocketManager(int listenPort, InetAddress bindto) throws 
SocketException {
+       public UdpSocketManager(int listenPort, InetAddress bindto, Node node) 
throws SocketException {
                super("UdpSocketManager sender thread on port " + listenPort);
+               this.node = node;
                    // Keep the Updater code in, just commented out, for now
                    // We may want to be able to do on-line updates.
 //                     if (Updater.hasResource()) {
@@ -133,6 +173,7 @@
        private void runLoop() {
                while (/*_active*/true) {
                        try {
+                               lastTimeInSeconds = (int) 
(System.currentTimeMillis() / 1000);
                                realRun();
                        } catch (Throwable t) {
                                Logger.error(this, "Caught " + t, t);
@@ -543,12 +584,12 @@
                return _usm;
        }

-       public static void init(int externalListenPort, InetAddress bindto)
-               throws SocketException
-       {
-               _usm = new UdpSocketManager(externalListenPort, bindto);
-       }
-
+//     public static void init(int externalListenPort, InetAddress bindto)
+//             throws SocketException
+//     {
+//             _usm = new UdpSocketManager(externalListenPort, bindto);
+//     }
+//
     public int getPortNumber() {
         return _sock.getLocalPort();
     }

Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2006-06-21 16:27:27 UTC (rev 
9336)
+++ trunk/freenet/src/freenet/node/Node.java    2006-06-21 16:48:37 UTC (rev 
9337)
@@ -369,7 +369,7 @@
        /** Maximum size of gzipped logfiles */
        static long maxLogSize;
        /** Log config handler */
-       static LoggingConfigHandler logConfigHandler;
+       public static LoggingConfigHandler logConfigHandler;

        /** If true, local requests and inserts aren't cached.
         * This opens up a glaring vulnerability; connected nodes
@@ -1084,7 +1084,7 @@
                        for(int i=0;i<200000;i++) {
                                int portNo = 1024 + random.nextInt(65535-1024);
                                try {
-                                       u = new UdpSocketManager(portNo, 
InetAddress.getByName(bindto));
+                                       u = new UdpSocketManager(portNo, 
InetAddress.getByName(bindto), this);
                                        port = u.getPortNumber();
                                        break;
                                } catch (Exception e) {
@@ -1098,7 +1098,7 @@
                                throw new 
NodeInitException(EXIT_NO_AVAILABLE_UDP_PORTS, "Could not find an available UDP 
port number for FNP (none specified)");
                } else {
                        try {
-                               u = new UdpSocketManager(port, 
InetAddress.getByName(bindto));
+                               u = new UdpSocketManager(port, 
InetAddress.getByName(bindto), this);
                        } catch (Exception e) {
                                throw new 
NodeInitException(EXIT_IMPOSSIBLE_USM_PORT, "Could not bind to port: "+port+" 
(node already running?)");
                        }

Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-06-21 16:27:27 UTC (rev 
9336)
+++ trunk/freenet/src/freenet/node/Version.java 2006-06-21 16:48:37 UTC (rev 
9337)
@@ -18,7 +18,7 @@
        public static final String protocolVersion = "1.0";

        /** The build number of the current revision */
-       private static final int buildNumber = 831;
+       private static final int buildNumber = 832;

        /** Oldest build of Fred we will talk to */
        private static final int lastGoodBuild = 765;


Reply via email to