[jboss-cvs] JBossAS SVN: r67160 - trunk/bootstrap/src/main/org/jboss/bootstrap.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Thu Nov 15 21:01:42 EST 2007


Author: dimitris at jboss.org
Date: 2007-11-15 21:01:42 -0500 (Thu, 15 Nov 2007)
New Revision: 67160

Modified:
   trunk/bootstrap/src/main/org/jboss/bootstrap/AbstractServerImpl.java
Log:
fix the shutdown logic so that errorcodes are returned to the shell.

Modified: trunk/bootstrap/src/main/org/jboss/bootstrap/AbstractServerImpl.java
===================================================================
--- trunk/bootstrap/src/main/org/jboss/bootstrap/AbstractServerImpl.java	2007-11-16 00:45:57 UTC (rev 67159)
+++ trunk/bootstrap/src/main/org/jboss/bootstrap/AbstractServerImpl.java	2007-11-16 02:01:42 UTC (rev 67160)
@@ -47,11 +47,12 @@
  * to boot the server.
  *
  * @author Scott.Stark at jboss.org
- * @author <a href="mailto:dimitris at jboss.org">Dimitris Andreadis</a>
+ * @author Dimitris.Andreadis at jboss.org
  * @author adrian at jboss.org
- * @version $Revision$
+ * @version $Revision:$
  */
-public abstract class AbstractServerImpl extends NotificationBroadcasterSupport implements Server, NotificationEmitter
+public abstract class AbstractServerImpl extends NotificationBroadcasterSupport
+   implements Server, NotificationEmitter
 {
    /** Instance logger. */
    protected Logger log;
@@ -70,11 +71,16 @@
 
    /** Flag to indicate if we are started. */
    private boolean started;
+   
    /** A flag indicating if start has been called */
    private boolean isInStart;
+   
    /** A flag indicating if shutdown has been called */
    private boolean isInShutdown;
 
+   /** A flag indicating if shutdownServer has been called */
+   private boolean isInternalShutdown;
+   
    /** The JVM shutdown hook */
    private ShutdownHook shutdownHook;
 
@@ -104,6 +110,7 @@
    {
       if (bootstrap == null)
          throw new IllegalArgumentException("Null bootstrap");
+      
       bootstraps.add(bootstrap);
    }
 
@@ -117,6 +124,7 @@
    {
       if (bootstrap == null)
          throw new IllegalArgumentException("Null bootstrap");
+      
       bootstraps.add(bootstrap);
    }
    
@@ -128,11 +136,11 @@
     * @throws IllegalStateException    Already initialized.
     * @throws Exception                Failed to initialize.
     */
-   public void init(final Properties props)
-      throws IllegalStateException, Exception
+   public void init(final Properties props) throws IllegalStateException, Exception
    {
       if (props == null)
          throw new IllegalArgumentException("props is null");
+      
       if (config != null)
          throw new IllegalStateException("already initialized");
 
@@ -151,6 +159,7 @@
 
    /**
     * Initialize server configuration and jvm settings.
+    * 
     * @param props
     * @throws Exception
     */
@@ -167,10 +176,9 @@
          System.setProperty("java.io.tmpdir", serverTmpDir.getCanonicalPath());
       }
 
-      /* Initialize the logging layer using the ServerImpl class. The server log
-      directory is initialized prior to this to ensure the jboss.server.log.dir
-      system property is set in case its used by the logging configs.
-      */
+      // Initialize the logging layer using the ServerImpl class. The server log
+      // directory is initialized prior to this to ensure the jboss.server.log.dir
+      //system property is set in case its used by the logging configs.
       config.getServerLogDir();
       log = Logger.getLogger(getClass());
 
@@ -198,6 +206,10 @@
 
       // make sure our impl type is exposed
       log.debug("Server type: " + getClass());
+      
+      // log the boot classloader
+      ClassLoader cl = getClass().getClassLoader();
+      log.debug("Server loaded through: " + cl.getClass().getName());      
 
       // Log the basic configuration elements
       log.info("Home Dir: " + config.getHomeDir());
@@ -226,7 +238,7 @@
       if (config.getRequireJBossURLStreamHandlerFactory())
       {
          internalInitURLHandlers();
-      } // end of if ()
+      }
       else
       {
          try
@@ -236,12 +248,12 @@
          catch (SecurityException e)
          {
             log.warn("You do not have permissions to set URLStreamHandlerFactory", e);
-         } // end of try-catch
+         }
          catch (Error e)
          {
             log.warn("URLStreamHandlerFactory already set", e);
-         } // end of catch
-      } // end of else
+         }
+      }
    }
 
    /**
@@ -260,8 +272,8 @@
          URLStreamHandlerFactory.preload();
       }
       catch (Error error)
-      { //very naughty but we HAVE to do this or
-         //we'll fail if we ever try to do this again
+      { // very naughty but we HAVE to do this or
+        // we'll fail if we ever try to do this again
          log.warn("Caught Throwable Error, this probably means " +
             "we've already set the URLStreamHAndlerFactory before"); 
       }
@@ -284,7 +296,6 @@
     * server has been initalized to use.
     *
     * @return          Typed server configuration object.
-    *
     * @throws IllegalStateException    Not initialized.
     */
    public ServerConfig getConfig() throws IllegalStateException
@@ -306,9 +317,9 @@
    }
 
    /**
-    Check if the shutdown operation has been called/is in progress.
-
-    @return true if shutdown has been called, false otherwise
+    * Check if the shutdown operation has been called/is in progress.
+    *
+    * @return true if shutdown has been called, false otherwise
     */
    public boolean isInShutdown()
    {
@@ -323,9 +334,9 @@
     */
    public void start() throws IllegalStateException, Exception
    {
-      synchronized( this )
+      synchronized (this)
       {
-         if( isInStart == false )
+         if (isInStart == false)
          {
             isInStart = true;
          }
@@ -352,12 +363,14 @@
 
          // See how long it takes us to start up
          StopWatch watch = new StopWatch(true);
-         // remeber when we we started
+
+         // Remember when we we started
          startDate = new Date();
 
          // Install the shutdown hook
          shutdownHook = new ShutdownHook();
          shutdownHook.setDaemon(true);
+         
          try
          {
             Runtime.getRuntime().addShutdownHook(shutdownHook);
@@ -390,23 +403,23 @@
          
          if (config.isInstallLifeThread())
          {
+            log.debug("Installing life thread " + lifeThread);            
             lifeThread = new LifeThread();
-            log.debug("Installing life thread " + lifeThread);
             lifeThread.start();
          }
 
          started = true;
 
-         // Send a JMX notification that the startup is complete
+         // Send a notification that the startup is complete
          Notification msg = new Notification(START_NOTIFICATION_TYPE, this, 1);
          msg.setUserData(new Long(watch.getLapTime()));
          sendNotification(msg); 
 
          watch.stop();
 
-         // Tell the world how fast it was =)
          if (jbossPackage != null)
          {
+            // Tell the world how fast it was =)
             log.info("JBoss (Microcontainer) [" + jbossPackage.getImplementationVersion() +
                      "] Started in " + watch);
          }
@@ -442,31 +455,28 @@
    protected abstract void doStart(StopWatch watch) throws Throwable;
 
    /**
+    * Override to perform the shutdown
+    */
+   protected abstract void doShutdown();
+   
+   /**
     * Shutdown the server
     */
    protected void shutdownServer()
    {
-      // Send a notification that mbeanServer stop is initiated
-      log.info("JBoss SHUTDOWN");
       if (log.isTraceEnabled())
          log.trace("Shutdown caller:", new Throwable("Here"));
-
-      // Execute the jdk JBossJDKLogManager doReset via reflection
-      LogManager lm = LogManager.getLogManager();
-      try
-      {
-         Class<?>[] sig = {};
-         Method doReset = lm.getClass().getDeclaredMethod("doReset", sig);
-         Object[] args = {};
-         doReset.invoke(lm, args);
-      }
-      catch(Exception e)
-      {
-         if(log.isTraceEnabled())
-            log.trace("No doReset found?", e);
-      }
-
-      Notification msg = new Notification(Server.STOP_NOTIFICATION_TYPE, this, 2);
+      
+      // avoid entering twice; may happen when called directly
+      // from AbstractServerImpl.shutdown(), then called again when all
+      // non-daemon threads have exited and the ShutdownHook runs. 
+      if (isInternalShutdown)
+         return;
+      else
+         isInternalShutdown = true;      
+      
+      // Send a notification that server stop is initiated
+      Notification msg = new Notification(STOP_NOTIFICATION_TYPE, this, 2);
       sendNotification(msg);
 
       // TODO Fix the TCL hack used here!
@@ -498,17 +508,13 @@
       }
       finally
       {
+         // Done
          log.info("Shutdown complete");
          System.out.println("Shutdown complete");
       }
    }
    
    /**
-    * Override to perform the shutdown
-    */
-   protected abstract void doShutdown();
-
-   /**
     * Shutdown the Server instance and run shutdown hooks.
     *
     * <p>If the exit on shutdown flag is true, then {@link #exit()}
@@ -518,75 +524,80 @@
     */
    public void shutdown() throws IllegalStateException
    {
+      if (log.isTraceEnabled())
+         log.trace("Shutdown caller:", new Throwable("Here"));
+      
       if (!started)
          throw new IllegalStateException("not started");
 
-      final AbstractServerImpl server = this;
-
-      log.debug("Shutting down");
-
+      if (isInShutdown)
+         throw new IllegalStateException("already in shutdown mode");
+      
       isInShutdown = true;
       boolean exitOnShutdown = config.getExitOnShutdown();
       boolean blockingShutdown = config.getBlockingShutdown();
-
+      log.info("Shutting down the server, blockingShutdown: " + blockingShutdown);
+      
       log.debug("exitOnShutdown: " + exitOnShutdown);
       log.debug("blockingShutdown: " + blockingShutdown);
 
-      if (lifeThread != null)
-      {
-         lifeThread.interrupt();
-         lifeThread = null;
-      }
-
       if (exitOnShutdown)
       {
-         log.debug("Calling server.exit(0)");
-         server.exit(0);
+         exit(0);
       }
-      else if (blockingShutdown)
-      {
-         log.debug("Invoking shutdown in calling thread");
-         shutdownServer();
-      }
       else
       {
-         // start in new thread to give positive
-         // feedback to requesting client of success.
-         new Thread()
+         // signal lifethread to exit; if no non-daemon threads
+         // remain, the JVM will eventually exit
+         lifeThread.interrupt();
+
+         if (blockingShutdown)
          {
-            public void run()
+            shutdownServer();
+         }
+         else
+         {
+            // start in new thread to give positive
+            // feedback to requesting client of success.
+            new Thread()
             {
-               // just run the hook, don't call System.exit, as we may
-               // be embeded in a vm that would not like that very much
-               log.debug("Invoking shutdown in background thread");
-               shutdownServer();
-            }
-         }.start();
+               public void run()
+               {
+                  // just run the hook, don't call System.exit, as we may
+                  // be embeded in a vm that would not like that very much
+                  shutdownServer();
+               }
+            }.start();
+         }
       }
    }
 
    /**
-    * Shutdown the server, the JVM and run shutdown hooks.
+    * Exit the JVM, run shutdown hooks, shutdown the server.
     *
     * @param exitcode   The exit code returned to the operating system.
     */
    public void exit(final int exitcode)
    {
-      // start in new thread so that we might have a chance to give positive
-      // feed back to requesting client of success.
+      // exit() in new thread so that we might have a chance to give positive
+      // feed back to requesting client of success.      
       new Thread()
       {
          public void run()
          {
-            log.info("Shutting down the JVM now!");
+            log.info("Server exit(" + exitcode + ") called");
+            
+            // Set exit code in the shutdown hook, in case halt is enabled
+            shutdownHook.setHaltExitCode(exitcode); 
+            
+            // Initiate exiting, shutdown hook will be called
             Runtime.getRuntime().exit(exitcode);
          }
       }.start();
    }
 
    /**
-    * Shutdown the server, the JVM and run shutdown hooks.  Exits with
-    * code 1.
+    * Exit the JVM with code 1, run shutdown hooks, shutdown the server.
     */
    public void exit()
    {
@@ -600,13 +611,13 @@
     */
    public void halt(final int exitcode)
    {
-      // start in new thread so that we might have a chance to give positive
+      // halt() in new thread so that we might have a chance to give positive
       // feed back to requesting client of success.
       new Thread()
       {
          public void run()
          {
-            System.err.println("Halting the system now!");
+            System.err.println("Server halt(" + exitcode + ") called, halting the JVM now!");
             Runtime.getRuntime().halt(exitcode);
          }
       }.start();
@@ -614,7 +625,7 @@
 
    /**
     * Forcibly terminates the currently running Java virtual machine.
-    * Exits with code 1.
+    * Halts with code 1.
     */
    public void halt()
    {
@@ -679,9 +690,9 @@
    }
 
 
-//////////////////////////////////////////////////////////////////////////   /
-//                             Server Information                           //
-//////////////////////////////////////////////////////////////////////////   /
+///////////////////////////////////////////////////////////////////////////
+//                             Server Information                        //
+///////////////////////////////////////////////////////////////////////////
 
    public Date getStartDate()
    {
@@ -732,16 +743,22 @@
       return version.getBuildDate();
    }
 
+   ///////////////////////////////////////////////////////////////////////////
+   //                             Lifecycle Thread                          //
+   ///////////////////////////////////////////////////////////////////////////
+   
    /** A simple thread that keeps the vm alive in the event there are no
     * other threads started.
     */ 
    private class LifeThread extends Thread
    {
       Object lock = new Object();
+      
       LifeThread()
       {
          super("JBossLifeThread");
       }
+      
       public void run()
       {
          synchronized (lock)
@@ -754,14 +771,22 @@
             {
             }
          }
-         log.info("LifeThread.run exits!");
+         log.info("LifeThread.run() exits!");
       }
    }
 
+   ///////////////////////////////////////////////////////////////////////////
+   //                             Shutdown Hook                             //
+   ///////////////////////////////////////////////////////////////////////////
+   
    private class ShutdownHook extends Thread
    {
+      /** Whether to halt the JMV at the end of the shutdown hook */      
       private boolean forceHalt = true;
 
+      /** The exit code to use if forceHalt is enabled */
+      private int haltExitCode;
+      
       public ShutdownHook()
       {
          super("JBoss Shutdown Hook");
@@ -773,13 +798,38 @@
          }
       }
 
+      public void setHaltExitCode(int haltExitCode)
+      {
+         this.haltExitCode = haltExitCode;
+      }
+      
       public void run()
       {
+         log.info("Runtime shutdown hook called, forceHalt: " + forceHalt);
+         
+         // shutdown the server
          shutdownServer();
+         
+         // Execute the jdk JBossJDKLogManager doReset via reflection
+         LogManager lm = LogManager.getLogManager();
+         try
+         {
+            Class<?>[] sig = {};
+            Method doReset = lm.getClass().getDeclaredMethod("doReset", sig);
+            Object[] args = {};
+            doReset.invoke(lm, args);
+         }
+         catch(Exception e)
+         {
+            if (log.isTraceEnabled())
+               log.trace("No doReset found?", e);
+         }
+         
+         // later bitch - other shutdown hooks may be killed
          if (forceHalt)
          {
             System.out.println("Halting VM");
-            Runtime.getRuntime().halt(0);
+            Runtime.getRuntime().halt(haltExitCode);
          }
       }
    }




More information about the jboss-cvs-commits mailing list