### Eclipse Workspace Patch 1.0
#P org.jboss.ide.eclipse.as.core
Index: jbosscore/org/jboss/ide/eclipse/as/core/server/internal/AbstractJBossBehaviourDelegate.java
===================================================================
--- jbosscore/org/jboss/ide/eclipse/as/core/server/internal/AbstractJBossBehaviourDelegate.java	(revision 41607)
+++ jbosscore/org/jboss/ide/eclipse/as/core/server/internal/AbstractJBossBehaviourDelegate.java	(working copy)
@@ -27,6 +27,10 @@
 
 	private PollThread pollThread = null;
 
+	protected PollThread getPollThread() {
+		return pollThread;
+	}
+	
 	public IServer getServer() {
 		return actualBehavior.getServer();
 	}
Index: jbosscore/org/jboss/ide/eclipse/as/core/util/PollThreadUtils.java
===================================================================
--- jbosscore/org/jboss/ide/eclipse/as/core/util/PollThreadUtils.java	(revision 41607)
+++ jbosscore/org/jboss/ide/eclipse/as/core/util/PollThreadUtils.java	(working copy)
@@ -13,13 +13,18 @@
 import java.util.List;
 import java.util.Properties;
 
+import org.eclipse.core.runtime.IStatus;
 import org.eclipse.wst.server.core.IServer;
 import org.jboss.ide.eclipse.as.core.ExtensionManager;
+import org.jboss.ide.eclipse.as.core.Trace;
+import org.jboss.ide.eclipse.as.core.extensions.polling.WebPortPoller;
 import org.jboss.ide.eclipse.as.core.server.INeedCredentials;
 import org.jboss.ide.eclipse.as.core.server.IPollResultListener;
 import org.jboss.ide.eclipse.as.core.server.IProvideCredentials;
 import org.jboss.ide.eclipse.as.core.server.IServerProvider;
 import org.jboss.ide.eclipse.as.core.server.IServerStatePoller;
+import org.jboss.ide.eclipse.as.core.server.IServerStatePoller2;
+import org.jboss.ide.eclipse.as.core.server.internal.DelegatingServerBehavior;
 import org.jboss.ide.eclipse.as.core.server.internal.JBossServer;
 import org.jboss.ide.eclipse.as.core.server.internal.PollThread;
 import org.jboss.ide.eclipse.as.core.server.internal.ServerAttributeHelper;
@@ -196,4 +201,23 @@
 			return returnedCredentials;
 		}
 	}
+	
+	/*
+	 * A solution needs to be found here. 
+	 * Should ideally use the poller that the server says is its poller,
+	 * but some pollers such as timeout poller cannot actively check
+	 */
+	public static IStatus isServerStarted(DelegatingServerBehavior jbsBehavior) {
+		IServerStatePoller poller = PollThreadUtils.getPoller(IServerStatePoller.SERVER_UP, jbsBehavior.getServer());
+		
+		// Need to be able to FORCE the poller to poll immediately
+		if( poller == null || !(poller instanceof IServerStatePoller2)) 
+			poller = new WebPortPoller();
+		IStatus started = ((IServerStatePoller2)poller).getCurrentStateSynchronous(jbsBehavior.getServer());
+		// Trace
+		Trace.trace(Trace.STRING_FINER, "Checking if a server is already started: " + started.getMessage()); //$NON-NLS-1$
+		
+		return started;
+	}
+
 }
Index: jbosscore/org/jboss/ide/eclipse/as/core/server/internal/launch/AbstractJBossStartLaunchConfiguration.java
===================================================================
--- jbosscore/org/jboss/ide/eclipse/as/core/server/internal/launch/AbstractJBossStartLaunchConfiguration.java	(revision 41607)
+++ jbosscore/org/jboss/ide/eclipse/as/core/server/internal/launch/AbstractJBossStartLaunchConfiguration.java	(working copy)
@@ -89,16 +89,7 @@
 	 * but some pollers such as timeout poller 
 	 */
 	protected IStatus isServerStarted(DelegatingServerBehavior jbsBehavior) {
-		IServerStatePoller poller = PollThreadUtils.getPoller(IServerStatePoller.SERVER_UP, jbsBehavior.getServer());
-		
-		// Need to be able to FORCE the poller to poll immediately
-		if( poller == null || !(poller instanceof IServerStatePoller2)) 
-			poller = new WebPortPoller();
-		IStatus started = ((IServerStatePoller2)poller).getCurrentStateSynchronous(jbsBehavior.getServer());
-		// Trace
-		Trace.trace(Trace.STRING_FINER, "Checking if a server is already started: " + started.getMessage()); //$NON-NLS-1$
-		
-		return started;
+		return PollThreadUtils.isServerStarted(jbsBehavior);
 	}
 	
 	protected boolean handleAlreadyStartedScenario(	DelegatingServerBehavior jbsBehavior, IStatus startedStatus) {
#P org.jboss.ide.eclipse.as.rse.core
Index: src/org/jboss/ide/eclipse/as/rse/core/AbstractRSEBehaviourDelegate.java
===================================================================
--- src/org/jboss/ide/eclipse/as/rse/core/AbstractRSEBehaviourDelegate.java	(revision 41607)
+++ src/org/jboss/ide/eclipse/as/rse/core/AbstractRSEBehaviourDelegate.java	(working copy)
@@ -13,9 +13,11 @@
 package org.jboss.ide.eclipse.as.rse.core;
 
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
 import org.eclipse.wst.server.core.IServer;
 import org.jboss.ide.eclipse.as.core.server.IServerStatePoller;
 import org.jboss.ide.eclipse.as.core.server.internal.AbstractJBossBehaviourDelegate;
+import org.jboss.ide.eclipse.as.core.util.PollThreadUtils;
 
 public abstract class AbstractRSEBehaviourDelegate extends AbstractJBossBehaviourDelegate {
 	
@@ -26,16 +28,22 @@
 	
 	@Override
 	public void stopImpl(boolean force) {
-		if( force ) {
+		// If force, or if the server is already started (force a one-time synchronous poll)
+		if( force || !PollThreadUtils.isServerStarted(actualBehavior).isOK()) {
 			forceStop();
+			return;
 		}
 
 		setServerStopping();
-		if (!gracefullStop().isOK()) {
+		IStatus shutdownStatus = gracefullStop();
+		if (!shutdownStatus.isOK()) {
+			// The shutdown failed. This indicates a bad command or nonfunctional shutdown command
+			if(getServer().getServerState() == IServer.STATE_STOPPED)
+				return; // The poller already changed state to stopped
+			
+			getPollThread().cancel();
 			setServerStarted();
-		} else {
-			setServerStopped();
-		}
+		} // else wait for the poller to set the proper state
 	}
 
 	@Override
Index: src/org/jboss/ide/eclipse/as/rse/core/RSEBehaviourDelegate.java
===================================================================
--- src/org/jboss/ide/eclipse/as/rse/core/RSEBehaviourDelegate.java	(revision 41607)
+++ src/org/jboss/ide/eclipse/as/rse/core/RSEBehaviourDelegate.java	(working copy)
@@ -19,6 +19,7 @@
 import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.osgi.util.NLS;
 import org.eclipse.rse.services.shells.IHostShell;
 import org.eclipse.wst.server.core.IServer;
 import org.jboss.ide.eclipse.as.core.extensions.events.ServerLogger;
@@ -45,8 +46,7 @@
 	@Override
 	protected IStatus gracefullStop() {
 		try {
-			executeShutdownCommand(getShutdownCommand(getServer()));
-			return Status.OK_STATUS;
+			return executeShutdownCommand(getShutdownCommand(getServer()));
 		} catch(CoreException ce) {
 			ServerLogger.getDefault().log(getServer(), ce.getStatus());
 			return new Status(
@@ -56,12 +56,19 @@
 		}
 	}
 
-	private void executeShutdownCommand(String shutdownCommand) throws CoreException {
+	protected IStatus executeShutdownCommand(String shutdownCommand) throws CoreException {
 		ServerShellModel model = RSEHostShellModel.getInstance().getModel(getServer());
-		model.executeRemoteCommand("/", shutdownCommand, new String[]{}, new NullProgressMonitor(), 10000, true);
-		IHostShell shell = model.getStartupShell();
-		if( RSEUtils.isActive(shell)) {
-			shell.writeToShell("exit");
+		int ret = model.executeRemoteCommandGetStatus("/", shutdownCommand, new String[]{}, new NullProgressMonitor(), 10000, true);
+		if( ret == -1 || ret == 0 ) {
+			// either a shutdown success or a failure on the part of the tools to accurately discover the exit code
+			// proceed as normal
+			IHostShell shell = model.getStartupShell();
+			if( RSEUtils.isActive(shell)) {
+				shell.writeToShell("exit");
+			}
+			return Status.OK_STATUS;
 		}
+		return new Status(IStatus.ERROR, RSECorePlugin.PLUGIN_ID, 
+				NLS.bind("Remote shutdown command failed with status {0}", ret));
 	}
 }
Index: src/org/jboss/ide/eclipse/as/rse/core/RSEHostShellModel.java
===================================================================
--- src/org/jboss/ide/eclipse/as/rse/core/RSEHostShellModel.java	(revision 41607)
+++ src/org/jboss/ide/eclipse/as/rse/core/RSEHostShellModel.java	(working copy)
@@ -20,6 +20,7 @@
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.core.runtime.Status;
+import org.eclipse.osgi.util.NLS;
 import org.eclipse.rse.core.RSECorePlugin;
 import org.eclipse.rse.core.model.IHost;
 import org.eclipse.rse.core.subsystems.ISubSystem;
@@ -32,6 +33,7 @@
 import org.eclipse.rse.subsystems.shells.core.subsystems.servicesubsystem.IShellServiceSubSystem;
 import org.eclipse.wst.server.core.IServer;
 import org.eclipse.wst.server.core.ServerCore;
+import org.jboss.ide.eclipse.as.core.Trace;
 import org.jboss.ide.eclipse.as.core.server.IJBASHostShellListener;
 import org.jboss.ide.eclipse.as.core.server.internal.DelegatingServerBehavior;
 import org.jboss.ide.eclipse.as.core.util.ThreadUtils;
@@ -128,7 +130,8 @@
 			try {
 				if( singleUseShell == null || !singleUseShell.isActive()) {
 					singleUseShell = service.launchShell(initialWorkingDirectory, environment, monitor);
-				} else {
+				} else if( initialWorkingDirectory != null ){
+					// allow for a null working directory to ensure no command is run here
 					singleUseShell.writeToShell("cd " + initialWorkingDirectory);
 				}
 				singleUseShell.writeToShell(command);
@@ -151,14 +154,72 @@
 					throws CoreException {
 			executeRemoteCommand(initialWorkingDirectory, command, environment, monitor);
 			ThreadUtils.sleepFor(delay);
-			if( exit ) {
+			if( exit && singleUseShell != null) {
 				singleUseShell.exit();
 				singleUseShell = null;
 			}
 		}
-		
-	}
 	
+		/**
+		 * Return a -1 if no idea what happened, or the actual status code from the shutdown command
+		 * 
+		 * @param initialWorkingDirectory
+		 * @param command
+		 * @param environment
+		 * @param monitor
+		 * @param delay
+		 * @param exit
+		 * @return
+		 * @throws CoreException
+		 */
+		public int executeRemoteCommandGetStatus( 
+				String initialWorkingDirectory, String command, 
+				String[] environment, IProgressMonitor monitor,
+				int delay, boolean exit)
+					throws CoreException {
+			executeRemoteCommand(initialWorkingDirectory, command, environment, monitor);
+			final String[] statusLine = new String[2]; // [0] is last, [1] is new
+			final boolean[] done = new boolean[1];
+			done[0] = false;
+			statusLine[0] = null;
+			IHostShellOutputListener statusListener = new IHostShellOutputListener() {
+				public void shellOutputChanged(IHostShellChangeEvent event) {
+					IHostOutput[] lines = event.getLines();
+					for( int i = 0; i < lines.length; i++ ) {
+						// shift
+						if( !done[0]) {
+							statusLine[0] = statusLine[1];
+							statusLine[1] = lines[i].getString();
+							System.out.println(lines[i].getString());
+						}
+						
+						if( serverId.equals(statusLine[1]))
+							// Then the real answer is the line before this one... statusLine[0]
+							done[0] = true;
+					}
+				}
+			};
+			singleUseShell.getStandardOutputReader().addOutputListener(statusListener);
+			
+			singleUseShell.writeToShell("echo $? && echo " + serverId);
+			ThreadUtils.sleepFor(delay);
+			if( exit && singleUseShell != null && singleUseShell.isActive() ) {
+				singleUseShell.exit();
+				singleUseShell = null;
+			}
+			String s = statusLine[0];
+			if( s != null ) {
+				try {
+					Integer i = Integer.parseInt(s);
+					return i.intValue();
+				} catch(NumberFormatException nfe) {
+				}
+			}
+			Trace.trace(Trace.STRING_FINER, NLS.bind("Command {0} exited with status {1}", command, statusLine[0]));
+			return -1;
+		}
+	}
+
 	public static IShellService findShellService(DelegatingServerBehavior behaviour) throws CoreException {
 		return findShellService(behaviour.getServer());
 	}
