[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