From: <ls...@us...> - 2008-10-12 20:00:56
|
Revision: 4626 http://jnode.svn.sourceforge.net/jnode/?rev=4626&view=rev Author: lsantha Date: 2008-10-12 20:00:40 +0000 (Sun, 12 Oct 2008) Log Message: ----------- Prorgess with isolates: clarification of exit reason, initial system exit support, child isolates. Modified Paths: -------------- trunk/core/src/classpath/ext/javax/isolate/Isolate.java trunk/core/src/classpath/ext/javax/isolate/IsolateStatus.java trunk/core/src/classpath/vm/java/lang/VMRuntime.java trunk/core/src/core/org/jnode/vm/isolate/IsolateStatusImpl.java trunk/core/src/core/org/jnode/vm/isolate/VmIsolate.java trunk/core/src/core/org/jnode/vm/scheduler/VmThread.java trunk/core/src/test/org/jnode/test/core/StatusLinkTest.java Modified: trunk/core/src/classpath/ext/javax/isolate/Isolate.java =================================================================== --- trunk/core/src/classpath/ext/javax/isolate/Isolate.java 2008-10-12 10:33:26 UTC (rev 4625) +++ trunk/core/src/classpath/ext/javax/isolate/Isolate.java 2008-10-12 20:00:40 UTC (rev 4626) @@ -21,24 +21,25 @@ package javax.isolate; +import gnu.java.security.action.GetPropertiesAction; +import java.security.AccessController; import java.util.Properties; -import java.security.AccessController; - import org.jnode.vm.isolate.VmIsolate; -import gnu.java.security.action.GetPropertiesAction; /** * @author Ewout Prangsma (ep...@us...) */ public final class Isolate { - /** The actual isolate implementation */ + /** + * The actual isolate implementation + */ private final VmIsolate impl; //todo hide this constructor /** * Constructor for the root isolate. - * + * * @param impl the JNode speciffic isolate implementation */ public Isolate(VmIsolate impl) { @@ -47,7 +48,7 @@ /** * Initialize this instance. - * + * * @param mainClass * @param args */ @@ -57,7 +58,7 @@ /** * Initialize this instance. - * + * * @param mainClass * @param args * @param properties @@ -80,7 +81,7 @@ /** * Gets the isolate that is running the current thread. - * + * * @return */ public static Isolate currentIsolate() { @@ -89,7 +90,7 @@ /** * If this object equal to the given object. - * + * * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object other) { @@ -98,7 +99,7 @@ /** * Request normal termination of this isolate. - * + * * @param status */ public void exit(int status) { @@ -107,17 +108,17 @@ /** * Force termination of this isolate. - * + * * @param status */ public void halt(int status) { - impl.halt(this, status); + impl.halt(status); } /** * Gets a new Link associated with this Isolate from which the current * isolate can receive status link messages. - * + * * @return * @throws ClosedLinkException */ @@ -127,7 +128,7 @@ /** * Start this isolate. - * + * * @param links * @throws IsolateStartupException */ @@ -141,43 +142,46 @@ * terminated. New isolates may have been constructed or existing ones terminated by the time method returns. * * @return the active Isolate objects present at the time of the call - * * @throws SecurityException if a security manager is present and permission to query isolates is denied */ public static Isolate[] getIsolates() { - //todo implement it - throw new UnsupportedOperationException(); + VmIsolate[] children = currentIsolate().impl.getChildren(); + int c_nr = children.length; + Isolate[] ret = new Isolate[c_nr]; + for (int i = 0; i < c_nr; i++) + ret[i] = children[i].getIsolate(); + + return ret; } /** * Returns the name of the main class of this isolate. - * + * * @return the name of the main class of this isolate */ public String getMainClassName() { - return impl.getMainClassName(); + return impl.getMainClassName(); } /** * Returns the current state of the isolate. * * @return the current state of an isolate - * * @throws IllegalStateException if called before the isolate is started - * @throws SecurityException if a security manager is present and permission to query isolates is denied + * @throws SecurityException if a security manager is present and permission to query isolates is denied */ - public IsolateStatus.State getState() { + public IsolateStatus.State getState() { return impl.getIsolateState(); } - + /** * Retrieves a copy of the Link array passed to start() by the current * isolate's creator. Modification of this array will have no effect on * subsequent invocation of this method. - * + * <p/> * This method never returns null: it will return a zero-length array if * this isolate's creator passed null to start(). - * + * * @return */ public static Link[] getLinks() { @@ -187,7 +191,7 @@ //todo hide this method /** * Gets the implementation instance. - * + * * @return */ final VmIsolate getImpl() { Modified: trunk/core/src/classpath/ext/javax/isolate/IsolateStatus.java =================================================================== --- trunk/core/src/classpath/ext/javax/isolate/IsolateStatus.java 2008-10-12 10:33:26 UTC (rev 4625) +++ trunk/core/src/classpath/ext/javax/isolate/IsolateStatus.java 2008-10-12 20:00:40 UTC (rev 4626) @@ -18,49 +18,75 @@ * along with this library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ - + package javax.isolate; +import org.jnode.vm.annotation.SharedStatics; + /** + * Represents isolate status, capturing such information as isolate state, exit code, and exit reason. + * State transitions in the isolate life cycle generate LinkMessages containing instances of this class + * which are sent over status links (but can be then forwarded over any link). If the isolate state is EXITED, + * the corresponding exit code and exit reason are contained in IsolateStatus. + * * @author Ewout Prangsma (ep...@us...) + * @author Levente S\u00e1ntha */ public class IsolateStatus { /** * Defines the state of an Isolate. - * + * * @author Ewout Prangsma (ep...@us...) */ + @SharedStatics public static enum State { - /** Isolate is starting */ + /** + * Isolate is starting + */ STARTING, - /** Isolate is started */ + /** + * Isolate is started + */ STARTED, - /** Isolate is exiting */ + /** + * Isolate is exiting + */ EXITING, - /** Isolate has exited */ + /** + * Isolate has exited + */ EXITED, - /** State is not known */ - UNKNOWN; + /** + * State is not known + */ + UNKNOWN } /** * Provides the reason for the termination of an isolate. - * + * * @author Ewout Prangsma (ep...@us...) */ + @SharedStatics public static enum ExitReason { - /** The last non-deamon thread exited */ + /** + * The last non-deamon thread exited + */ IMPLICIT_EXIT, - /** Another isolate invoked Isolate.exit */ + /** + * Another isolate invoked Isolate.exit + */ OTHER_EXIT, - /** Another isolate invoed Isolated.halt */ + /** + * Another isolate invoed Isolated.halt + */ OTHER_HALT, /** @@ -74,55 +100,91 @@ */ SELF_HALT, - /** The last non-deamon thread exited due to an uncaught exception */ - UNCAUGHT_EXCEPTION; + /** + * The last non-deamon thread exited due to an uncaught exception + */ + UNCAUGHT_EXCEPTION } - + private final ExitReason exitReason; private final State state; private final int exitCode; - + /** * Initialize this instance. + * * @param state * @param exitReason * @param exitCode */ protected IsolateStatus(State state, ExitReason exitReason, int exitCode) { + if (state == null) + throw new IllegalArgumentException(); + + if (state.equals(State.EXITED) && exitReason == null) + throw new IllegalArgumentException(); + this.state = state; this.exitReason = exitReason; this.exitCode = exitCode; } - + /** - * Are this and the given object equal. - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(Object other) { - return super.equals(other); - } - - /** * Gets the exit reason. + * * @return */ public ExitReason getExitReason() { return exitReason; } - + /** * Gets the exit code. + * * @return */ public int getExitCode() { return exitCode; } - + /** * Gets the state of the isolate. + * * @return */ public State getState() { return state; } + + /** + * @param o + * @return + */ + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof IsolateStatus)) return false; + + IsolateStatus that = (IsolateStatus) o; + + if (!state.equals(that.state)) return false; + + if (state.equals(State.EXITED)) { + if (exitCode != that.exitCode) return false; + if (exitReason != that.exitReason) return false; + } + + return true; + } + + /** + * @return + */ + public int hashCode() { + int result = state.hashCode(); + if (state.equals(State.EXITED)) { + result = 31 * result + exitReason.hashCode(); + result = 31 * result + exitCode; + } + return result; + } } Modified: trunk/core/src/classpath/vm/java/lang/VMRuntime.java =================================================================== --- trunk/core/src/classpath/vm/java/lang/VMRuntime.java 2008-10-12 10:33:26 UTC (rev 4625) +++ trunk/core/src/classpath/vm/java/lang/VMRuntime.java 2008-10-12 20:00:40 UTC (rev 4626) @@ -28,6 +28,8 @@ import org.jnode.vm.VmProcess; import org.jnode.vm.VmSystem; import org.jnode.vm.VmExit; +import org.jnode.vm.isolate.VmIsolate; +import javax.isolate.Isolate; /** * VMRuntime represents the interface to the Virtual Machine. @@ -153,7 +155,11 @@ * @param status the status to end the process with */ static void exit(int status) { - throw new VmExit(status); + if(VmIsolate.getRoot() == VmIsolate.currentIsolate()){ + throw new VmExit(status); + } else { + VmIsolate.currentIsolate().systemExit(Isolate.currentIsolate(), status); + } } /** Modified: trunk/core/src/core/org/jnode/vm/isolate/IsolateStatusImpl.java =================================================================== --- trunk/core/src/core/org/jnode/vm/isolate/IsolateStatusImpl.java 2008-10-12 10:33:26 UTC (rev 4625) +++ trunk/core/src/core/org/jnode/vm/isolate/IsolateStatusImpl.java 2008-10-12 20:00:40 UTC (rev 4626) @@ -9,10 +9,15 @@ * @author Levente S\u00e1ntha */ public class IsolateStatusImpl extends IsolateStatus implements Cloneable { - public IsolateStatusImpl(State state, ExitReason exitReason, int exitCode) { - super(state, exitReason, exitCode); + + public IsolateStatusImpl(State state) { + super(state, null, 0); } + public IsolateStatusImpl(ExitReason exitReason, int exitCode) { + super(State.EXITED, exitReason, exitCode); + } + @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); @@ -30,7 +35,7 @@ public String toString() { State s = getState(); if (s.equals(State.EXITED)) { - return getState() + "(" + getExitReason() + "," + getExitCode(); + return getState() + "(" + getExitReason() + "," + getExitCode() + ")"; } else { return getState().toString(); } Modified: trunk/core/src/core/org/jnode/vm/isolate/VmIsolate.java =================================================================== --- trunk/core/src/core/org/jnode/vm/isolate/VmIsolate.java 2008-10-12 10:33:26 UTC (rev 4625) +++ trunk/core/src/core/org/jnode/vm/isolate/VmIsolate.java 2008-10-12 20:00:40 UTC (rev 4626) @@ -153,6 +153,8 @@ */ private BootableHashMap<VmIsolateLocal<?>, ?> isolateLocalMap = new BootableHashMap<VmIsolateLocal<?>, Object>(); + private List<VmIsolate> children = new LinkedList<VmIsolate>(); + /** * Isolate states. * @@ -369,23 +371,49 @@ return isolate; } + public final void exit(Isolate isolate, int status) { + exit0(isolate, status); + } + + public final void systemExit(Isolate isolate, int status) { + //only this isolate may call this method + testIsolate(isolate); + + this.exitReason = IsolateStatus.ExitReason.SELF_EXIT; + this.exitCode = status; + + int ac = threadGroup.activeCount(); + if (ac > 0) { + Thread[] ta = new Thread[ac]; + int rc = threadGroup.enumerate(ta); + Thread current = Thread.currentThread(); + boolean found = false; + for (int i = 0; i < rc; i++) { + Thread thread = ta[i]; + if (current != thread) { + thread.getVmThread().stopForced(null); + } else { + found = true; + } + } + if (found) { + current.getVmThread().stop(null); + } + } + } + /** * Request normal termination of this isolate. * * @param status */ - public final void exit(Isolate isolate, int status) { - testIsolate(isolate); + public final void exit0(Isolate isolate, int status) { + //testIsolate(isolate); //todo handle demon threads if (threadGroup.activeCount() > 0 || threadGroup.activeGroupCount() > 0) return; changeState(State.EXITING); - try { - threadGroup.destroy(); - } catch (Throwable t) { - t.printStackTrace(); - } this.exitCode = status; if (currentIsolate() == this) { @@ -395,18 +423,60 @@ this.exitReason = IsolateStatus.ExitReason.OTHER_EXIT; } - changeState(State.EXITED); - StaticData.isolates.remove(this); + doExit(); } /** + * Request normal termination of this isolate. + * + * @param status + */ + public final void implicitExit(int status) { + //on this isolate may call this method + testIsolate(currentIsolate().isolate); + + //todo handle demon threads + if (threadGroup.activeCount() > 0 || threadGroup.activeGroupCount() > 0) + return; + + changeState(State.EXITING); + + if (exitReason == null) { + exitReason = IsolateStatus.ExitReason.IMPLICIT_EXIT; + this.exitCode = status; + } + + doExit(); + } + + /** + * Request normal termination of this isolate. + * + * @param status + */ + public final void uncaughtExceptionExit() { + //on this isolate may call this method + testIsolate(currentIsolate().isolate); + + //todo handle demon threads + if (threadGroup.activeCount() > 0 || threadGroup.activeGroupCount() > 0) + return; + + changeState(State.EXITING); + + exitReason = IsolateStatus.ExitReason.UNCAUGHT_EXCEPTION; + this.exitCode = -1; + + doExit(); + } + + /** * Force termination of this isolate. * * @param status */ @SuppressWarnings("deprecation") - public final void halt(Isolate isolate, int status) { - testIsolate(isolate); + public final void halt(int status) { changeState(State.EXITING); switch (state) { case EXITING: @@ -414,19 +484,28 @@ break; } + if (currentIsolate() == this) { + this.exitReason = IsolateStatus.ExitReason.SELF_HALT; + } else { + this.exitReason = IsolateStatus.ExitReason.OTHER_HALT; + } + + this.exitCode = status; + + doExit(); + } + + private void doExit() { try { threadGroup.destroy(); } catch (Throwable t) { t.printStackTrace(); } - this.exitCode = status; - if (currentIsolate() == this) { - this.exitReason = IsolateStatus.ExitReason.SELF_HALT; - } else { - this.exitReason = IsolateStatus.ExitReason.OTHER_HALT; - } + + this.creator.removeChild(this); + StaticData.isolates.remove(this); + changeState(State.EXITED); - StaticData.isolates.remove(this); } /** @@ -677,6 +756,8 @@ // Update the state of this isolate. changeState(State.STARTED); + //add to parent + this.creator.addChild(this); // Run main method. mainMethod.invoke(null, new Object[]{args}); @@ -842,10 +923,21 @@ private void sendStatus(VmLink link, IsolateStatus.State state) { if (state.equals(IsolateStatus.State.EXITED)) { - org.jnode.vm.Unsafe.debugStackTrace(); - link.sendStatus(new StatusLinkMessage(new IsolateStatusImpl(state, exitReason, exitCode))); + link.sendStatus(new StatusLinkMessage(new IsolateStatusImpl(exitReason, exitCode))); } else { - link.sendStatus(new StatusLinkMessage(new IsolateStatusImpl(state, null, -1))); + link.sendStatus(new StatusLinkMessage(new IsolateStatusImpl(state))); } } + + private synchronized void addChild(VmIsolate child) { + this.children.add(child); + } + + private synchronized void removeChild(VmIsolate child) { + this.children.remove(child); + } + + public synchronized VmIsolate[] getChildren() { + return this.children.toArray(new VmIsolate[children.size()]); + } } Modified: trunk/core/src/core/org/jnode/vm/scheduler/VmThread.java =================================================================== --- trunk/core/src/core/org/jnode/vm/scheduler/VmThread.java 2008-10-12 10:33:26 UTC (rev 4625) +++ trunk/core/src/core/org/jnode/vm/scheduler/VmThread.java 2008-10-12 20:00:40 UTC (rev 4626) @@ -32,6 +32,7 @@ import org.jnode.vm.VmStackReader; import org.jnode.vm.VmSystem; import org.jnode.vm.VmSystemObject; +import org.jnode.vm.isolate.VmIsolate; import org.jnode.vm.annotation.Inline; import org.jnode.vm.annotation.Internal; import org.jnode.vm.annotation.KernelSpace; @@ -47,7 +48,6 @@ import org.jnode.vm.memmgr.VmHeapManager; import org.vmmagic.pragma.UninterruptiblePragma; import org.vmmagic.unboxed.Address; -import javax.isolate.Isolate; /** * VM thread implementation @@ -390,7 +390,10 @@ if (javaThread != null) { javaThread.onExit(); //exit the current isolate if needed - Isolate.currentIsolate().exit(0); + if (ex instanceof ThreadDeath) + VmIsolate.currentIsolate().implicitExit(0); + else + VmIsolate.currentIsolate().uncaughtExceptionExit(); // Notify joining threads synchronized (javaThread) { javaThread.notifyAll(); @@ -407,6 +410,26 @@ * @param ex * @throws UninterruptiblePragma */ + public final void stopForced(Throwable ex) throws UninterruptiblePragma { + this.stopping = true; + if (javaThread != null) { + javaThread.onExit(); + // Notify joining threads + synchronized (javaThread) { + javaThread.notifyAll(); + } + } + + // Do the low level stop uninterrupted + doStop(); + } + + /** + * Stop the thread permanently. + * + * @param ex + * @throws UninterruptiblePragma + */ @Uninterruptible private final void doStop() { final VmProcessor proc = VmMagic.currentProcessor(); @@ -722,17 +745,22 @@ */ @LoadStatics protected static final void runThread(VmThread thread) { + Throwable t = null; try { thread.asThread().run(); } catch (Throwable ex) { try { + t = ex; ex.printStackTrace(); } catch (Throwable ex2) { /* Ignore */ } } finally { try { - thread.stop(new ThreadDeath()); + if (t == null) + thread.stop(new ThreadDeath()); + else + thread.stop(t); } catch (Throwable ex) { /* Ignore */ while (true) { Modified: trunk/core/src/test/org/jnode/test/core/StatusLinkTest.java =================================================================== --- trunk/core/src/test/org/jnode/test/core/StatusLinkTest.java 2008-10-12 10:33:26 UTC (rev 4625) +++ trunk/core/src/test/org/jnode/test/core/StatusLinkTest.java 2008-10-12 20:00:40 UTC (rev 4626) @@ -4,7 +4,6 @@ package org.jnode.test.core; import java.io.IOException; -import java.io.InterruptedIOException; import javax.isolate.Isolate; import javax.isolate.IsolateStartupException; import javax.isolate.IsolateStatus; @@ -13,7 +12,7 @@ public class StatusLinkTest { - public static void main(String[] args) throws IsolateStartupException, InterruptedIOException, IOException { + public static void main(String[] args) throws IsolateStartupException, IOException { String clsName = ChildClass.class.getName(); Isolate child = new Isolate(clsName); Link link = child.newStatusLink(); @@ -34,6 +33,7 @@ LinkMessage msg = link.receive(); if (msg.containsStatus()) { IsolateStatus is = msg.extractStatus(); + System.out.println("Isolate status: " + is); if (is.getState().equals(IsolateStatus.State.EXITED)) { System.out.println("Message: state=" + is.getState() + " code=" + is.getExitCode() + " reason=" + is.getExitReason()); @@ -57,6 +57,23 @@ System.out.println("Child: started"); System.out.println("Child: sleeping 3 seconds"); Thread.sleep(3000); + //if(true) + // throw new RuntimeException(); + new Thread(new Runnable() { + public void run() { + try { + System.out.println("Child thread: started"); + System.out.println("Child thread: sleeping 3 seconds"); + Thread.sleep(3000); + if (true) + throw new RuntimeException(); + System.out.println("Child thread: exiting"); + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } + }).start(); + System.out.println("Child: exiting"); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |