From: <cr...@us...> - 2009-01-09 12:34:42
|
Revision: 4836 http://jnode.svn.sourceforge.net/jnode/?rev=4836&view=rev Author: crawley Date: 2009-01-09 12:26:02 +0000 (Fri, 09 Jan 2009) Log Message: ----------- Fix for the proclet stream cycle bug Modified Paths: -------------- trunk/core/src/core/org/jnode/util/ProxyStream.java trunk/shell/src/shell/org/jnode/shell/proclet/ProcletContext.java trunk/shell/src/shell/org/jnode/shell/proclet/ProcletIOContext.java trunk/shell/src/shell/org/jnode/shell/proclet/ProcletProxyInputStream.java trunk/shell/src/shell/org/jnode/shell/proclet/ProcletProxyPrintStream.java Modified: trunk/core/src/core/org/jnode/util/ProxyStream.java =================================================================== --- trunk/core/src/core/org/jnode/util/ProxyStream.java 2009-01-07 11:45:52 UTC (rev 4835) +++ trunk/core/src/core/org/jnode/util/ProxyStream.java 2009-01-09 12:26:02 UTC (rev 4836) @@ -46,16 +46,4 @@ * @return the wrapped stream for this proxy. */ public T getProxiedStream() throws ProxyStreamException; - - /** - * Determine if this proxy refers to the same underlying stream as another - * stream object. - * - * @param other - * @return <code>true</code> if this object and <code>other</code> - * resolve to the same underlying stream, otherwise false. Note: the - * 'otherwise' covers cases where <code>other</code> is - * <code>null</code>. - */ - public boolean sameStream(T other) throws ProxyStreamException; } Modified: trunk/shell/src/shell/org/jnode/shell/proclet/ProcletContext.java =================================================================== --- trunk/shell/src/shell/org/jnode/shell/proclet/ProcletContext.java 2009-01-07 11:45:52 UTC (rev 4835) +++ trunk/shell/src/shell/org/jnode/shell/proclet/ProcletContext.java 2009-01-09 12:26:02 UTC (rev 4836) @@ -34,6 +34,7 @@ import org.jnode.util.ProxyStreamException; import org.jnode.vm.VmExit; import org.jnode.vm.VmSystem; +import org.jnode.vm.isolate.VmIsolate; /** * This class implements the proclet-specific state used in the JNode proclet @@ -46,8 +47,9 @@ * @author cr...@jn... */ public class ProcletContext extends ThreadGroup { + public static final int NO_SUCH_PID = 0; + private Properties properties; - private Object[] streams; private Map<String, String> environment; private int threadCount; private final int pid; @@ -66,8 +68,8 @@ properties = parentContext.properties; } if (properties == null) { - properties = AccessController - .doPrivileged(new PrivilegedAction<Properties>() { + properties = AccessController.doPrivileged( + new PrivilegedAction<Properties>() { public Properties run() { return System.getProperties(); } @@ -76,19 +78,13 @@ properties = (Properties) properties.clone(); } if (streams == null) { - if (parentContext != null) { - streams = parentContext.streams; - } - if (streams == null) { - try { - streams = new Object[] { - resolve(System.in), resolve(System.out), resolve(System.err)}; - } catch (ProxyStreamException ex) { - throw new ProcletException("Broken streams", ex); - } - } else { - streams = (Object[]) streams.clone(); - } + try { + streams = new Object[] { + resolve(System.in), resolve(System.out), resolve(System.err) + }; + } catch (ProxyStreamException ex) { + throw new ProcletException("Broken streams", ex); + } } if (environment == null) { if (parentContext != null) { @@ -100,14 +96,17 @@ } this.environment = environment; this.properties = properties; - this.streams = streams; this.pid = extractPid(getName()); + ((ProcletIOContext) VmIsolate.getRoot().getIOContext()).setStreamsForNewProclet(pid, streams); setDaemon(true); } private Closeable resolve(Closeable stream) throws ProxyStreamException { - return (stream instanceof ProxyStream) ? ((ProxyStream<?>) stream) - .getProxiedStream() : stream; + if (stream instanceof ProxyStream) { + return ((ProxyStream<?>) stream).getProxiedStream(); + } else { + return stream; + } } /** @@ -127,44 +126,6 @@ return properties; } - /** - * Set the stream object that corresponds to a given 'fd'. - * - * @param fd a non-negative index into the streams vector. - * @param stream the stream object to set. - */ - synchronized void setStream(int fd, Object stream) { - if (stream instanceof ProcletProxyStream) { - throw new IllegalArgumentException( - "stream is a proclet proxy stream"); - } - if (fd < 0) { - throw new IllegalArgumentException("fd is negative"); - } - if (fd >= streams.length) { - Object[] tmp = new Object[fd + 1]; - System.arraycopy(streams, 0, tmp, 0, streams.length); - streams = tmp; - } - streams[fd] = stream; - } - - /** - * Get the stream object that corresponds to a given 'fd'. - * - * @param fd a non-negative index into the streams vector. - * @return the stream object, or <code>null</code> - */ - public synchronized Object getStream(int fd) { - if (fd < 0) { - throw new IllegalArgumentException("fd is negative"); - } else if (fd > streams.length) { - return null; - } else { - return streams[fd]; - } - } - public synchronized void setProperties(Properties properties) { this.properties = properties; } Modified: trunk/shell/src/shell/org/jnode/shell/proclet/ProcletIOContext.java =================================================================== --- trunk/shell/src/shell/org/jnode/shell/proclet/ProcletIOContext.java 2009-01-07 11:45:52 UTC (rev 4835) +++ trunk/shell/src/shell/org/jnode/shell/proclet/ProcletIOContext.java 2009-01-09 12:26:02 UTC (rev 4836) @@ -24,118 +24,105 @@ import java.io.InputStream; import java.io.PrintStream; -import org.jnode.util.ProxyStreamException; import org.jnode.vm.IOContext; import org.jnode.vm.VmSystem; /** + * The ProcletIOContext is an IOContext implementation that uses Proxy streams to + * direct System.in/out/err traffic to different places depending on the current + * proclet. + * * @author Levente S\u00e1ntha * @author cr...@jn... */ public class ProcletIOContext implements IOContext { - private static InputStream globalInStream; - private static PrintStream globalOutStream; - private static PrintStream globalErrStream; - private static boolean initialized; + public static final int GLOBAL_STREAM_ID = ProcletContext.NO_SUCH_PID; + public ProcletIOContext() { - initGlobals(); } - private static synchronized void initGlobals() { - if (!initialized) { - globalInStream = System.in; - globalOutStream = System.out; - globalErrStream = System.err; - initialized = true; - } + public synchronized void setGlobalInStream(InputStream is) { + doSetIn(is, GLOBAL_STREAM_ID); } - public void setGlobalInStream(InputStream in) { - globalInStream = in; + public synchronized void setGlobalOutStream(PrintStream ps) { + doSetOut(ps, GLOBAL_STREAM_ID); } - public void setGlobalOutStream(PrintStream out) { - globalOutStream = out; + public synchronized void setGlobalErrStream(PrintStream is) { + doSetErr(is, GLOBAL_STREAM_ID); } - public PrintStream getGlobalOutStream() { - return globalOutStream; + public synchronized InputStream getGlobalInStream() { + return ((ProcletProxyInputStream) System.in).getProxiedStream(GLOBAL_STREAM_ID); } - public void setGlobalErrStream(PrintStream err) { - globalErrStream = err; + public synchronized PrintStream getGlobalOutStream() { + return ((ProcletProxyPrintStream) System.out).getProxiedStream(GLOBAL_STREAM_ID); } - public PrintStream getGlobalErrStream() { - return globalErrStream; + public synchronized PrintStream getGlobalErrStream() { + return ((ProcletProxyPrintStream) System.err).getProxiedStream(GLOBAL_STREAM_ID); } - public InputStream getGlobalInStream() { - return globalInStream; + public synchronized void setSystemIn(InputStream is) { + doSetIn(is, getCurrentPid()); } - public void setSystemIn(InputStream in) { - if (in instanceof ProcletProxyInputStream) { - try { - in = ((ProcletProxyInputStream) in).getProxiedStream(); - } catch (ProxyStreamException ex) { - throw new ProcletException("Cannot resolve 'in'", ex); - } - } + public synchronized void setSystemOut(PrintStream ps) { + doSetOut(ps, getCurrentPid()); + } + + public synchronized void setSystemErr(PrintStream ps) { + doSetErr(ps, getCurrentPid()); + } + + private int getCurrentPid() { ProcletContext procletContext = ProcletContext.currentProcletContext(); - if (procletContext != null) { - procletContext.setStream(0, in); - } else { - globalInStream = in; + return (procletContext == null) ? GLOBAL_STREAM_ID : procletContext.getPid(); + } + + private void doSetIn(InputStream is, int pid) { + if (is instanceof ProcletProxyInputStream) { + is = ((ProcletProxyInputStream) is).getProxiedStream(pid); } + ProcletProxyInputStream newProxyStream = new ProcletProxyInputStream( + (ProcletProxyInputStream) System.in, is, pid); + VmSystem.setStaticField(System.class, "in", newProxyStream); } - public void setSystemOut(PrintStream out) { - if (out instanceof ProcletProxyPrintStream) { - try { - out = ((ProcletProxyPrintStream) out).getProxiedStream(); - } catch (ProxyStreamException ex) { - throw new ProcletException("Cannot resolve 'out'", ex); - } + private void doSetOut(PrintStream ps, int pid) { + if (ps instanceof ProcletProxyPrintStream) { + ps = ((ProcletProxyPrintStream) ps).getProxiedStream(pid); } - ProcletContext procletContext = ProcletContext.currentProcletContext(); - if (procletContext != null) { - procletContext.setStream(1, out); - } else { - globalOutStream = out; - } + ProcletProxyPrintStream newProxyStream = new ProcletProxyPrintStream( + (ProcletProxyPrintStream) System.out, ps, pid); + VmSystem.setStaticField(System.class, "out", newProxyStream); } - public void setSystemErr(PrintStream err) { - if (err instanceof ProcletProxyPrintStream) { - try { - err = ((ProcletProxyPrintStream) err).getProxiedStream(); - } catch (ProxyStreamException ex) { - throw new ProcletException("Cannot resolve 'err'", ex); - } + private void doSetErr(PrintStream ps, int pid) { + if (ps instanceof ProcletProxyPrintStream) { + ps = ((ProcletProxyPrintStream) ps).getProxiedStream(pid); } - ProcletContext procletContext = ProcletContext.currentProcletContext(); - if (procletContext != null) { - procletContext.setStream(2, err); - } else { - globalErrStream = err; - } + ProcletProxyPrintStream newProxyStream = new ProcletProxyPrintStream( + (ProcletProxyPrintStream) System.err, ps, pid); + VmSystem.setStaticField(System.class, "err", newProxyStream); } - public void enterContext() { + public synchronized void enterContext() { VmSystem.setStaticField(System.class, "in", - new ProcletProxyInputStream()); + new ProcletProxyInputStream(System.in, 0)); VmSystem.setStaticField(System.class, "out", - new ProcletProxyPrintStream(1)); + new ProcletProxyPrintStream(System.out, 1)); VmSystem.setStaticField(System.class, "err", - new ProcletProxyPrintStream(2)); + new ProcletProxyPrintStream(System.err, 2)); } - public void exitContext() { - InputStream in = globalInStream; - PrintStream out = globalOutStream; - PrintStream err = globalErrStream; + public synchronized void exitContext() { + InputStream in = getGlobalInStream(); + PrintStream out = getGlobalOutStream(); + PrintStream err = getGlobalErrStream(); if (in instanceof ProcletProxyStream) { throw new ProcletException( @@ -154,30 +141,27 @@ VmSystem.setStaticField(System.class, "err", err); } - public PrintStream getRealSystemErr() { - ProcletContext procletContext = ProcletContext.currentProcletContext(); - if (procletContext != null) { - return (PrintStream) procletContext.getStream(2); - } else { - return globalErrStream; - } + public synchronized PrintStream getRealSystemErr() { + return ((ProcletProxyPrintStream) System.err).getProxiedStream(getCurrentPid()); } - public InputStream getRealSystemIn() { - ProcletContext procletContext = ProcletContext.currentProcletContext(); - if (procletContext != null) { - return (InputStream) procletContext.getStream(0); - } else { - return globalInStream; - } + public synchronized InputStream getRealSystemIn() { + return ((ProcletProxyInputStream) System.in).getProxiedStream(getCurrentPid()); } - public PrintStream getRealSystemOut() { - ProcletContext procletContext = ProcletContext.currentProcletContext(); - if (procletContext != null) { - return (PrintStream) procletContext.getStream(1); - } else { - return globalOutStream; - } + public synchronized PrintStream getRealSystemOut() { + return ((ProcletProxyPrintStream) System.out).getProxiedStream(getCurrentPid()); } + + synchronized void setStreamsForNewProclet(int pid, Object[] streams) { + ProcletProxyInputStream in = new ProcletProxyInputStream( + (ProcletProxyInputStream) System.in, (InputStream) streams[0], pid); + ProcletProxyPrintStream out = new ProcletProxyPrintStream( + (ProcletProxyPrintStream) System.out, (PrintStream) streams[1], pid); + ProcletProxyPrintStream err = new ProcletProxyPrintStream( + (ProcletProxyPrintStream) System.err, (PrintStream) streams[2], pid); + VmSystem.setStaticField(System.class, "in", in); + VmSystem.setStaticField(System.class, "out", out); + VmSystem.setStaticField(System.class, "err", err); + } } Modified: trunk/shell/src/shell/org/jnode/shell/proclet/ProcletProxyInputStream.java =================================================================== --- trunk/shell/src/shell/org/jnode/shell/proclet/ProcletProxyInputStream.java 2009-01-07 11:45:52 UTC (rev 4835) +++ trunk/shell/src/shell/org/jnode/shell/proclet/ProcletProxyInputStream.java 2009-01-09 12:26:02 UTC (rev 4836) @@ -23,10 +23,11 @@ import java.io.IOException; import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; import org.jnode.util.ProxyStream; import org.jnode.util.ProxyStreamException; -import org.jnode.vm.VmSystem; /** * This class provides a proxy mechanism for System.in. If the current thread is @@ -38,28 +39,48 @@ */ public class ProcletProxyInputStream extends InputStream implements ProcletProxyStream<InputStream> { + + private Map<Integer, InputStream> streamMap; private int fd; /** - * Construct a proxy input stream for 'standard input'; i.e. fd = 0; - */ - public ProcletProxyInputStream() { - this(0); - } - - /** * Construct a proxy input stream for a designated fd. Note that if the fd * is non-zero, the proxy will not work in a non-ProcletContext context, and * not work in the ProcletContext context if the fd doesn't correspond to an * InputStream. * + * @param is the initial value for globalInput. * @param fd */ - public ProcletProxyInputStream(int fd) { + public ProcletProxyInputStream(InputStream is, int fd) { this.fd = fd; + streamMap = new HashMap<Integer, InputStream>(); + if (is == null) { + throw new IllegalArgumentException("null stream"); + } + streamMap.put(ProcletIOContext.GLOBAL_STREAM_ID, is); } + /** + * Construct a proxy input stream based on the state of the supplied proxy. + * The new proxy has all entries of the existing one except that the entry + * for pid is set / reset to in. + * + * @param proxy + * @param is + * @param pid + */ + public ProcletProxyInputStream(ProcletProxyInputStream proxy, InputStream is, + int pid) { + if (is == null) { + throw new IllegalArgumentException("null stream"); + } + streamMap = new HashMap<Integer, InputStream>(proxy.streamMap); + streamMap.put(pid, is); + fd = proxy.fd; + } + @Override public int read() throws IOException { return getRealStream().read(); @@ -124,43 +145,25 @@ } public InputStream getProxiedStream() throws ProxyStreamException { - ThreadGroup threadGroup = Thread.currentThread().getThreadGroup(); - if (threadGroup instanceof ProcletContext) { - try { - Object stream = ((ProcletContext) threadGroup).getStream(fd); - if (stream instanceof ProcletProxyStream) { - throw new ProxyStreamException( - "Proclet stream points to another proclet stream"); - } - if (stream instanceof ProxyStream) { - stream = ((ProxyStream<?>) stream).getRealStream(); - } - return (InputStream) stream; - } catch (Exception ex) { - throw new ProxyStreamException("Proclet input broken for fd = " - + fd, ex); - } - } else { - if (fd != 0) { - throw new ProxyStreamException( - "Proclet input broken: wrong fd = " + fd); - } - return VmSystem.getGlobalInStream(); + ProcletContext procletContext = ProcletContext.currentProcletContext(); + int pid = (procletContext == null) ? ProcletIOContext.GLOBAL_STREAM_ID : procletContext.getPid(); + InputStream is = streamMap.get(pid); + if (is == null) { + throw new ProxyStreamException( + "Proclet stream not set (fd = " + fd + ")"); + } else if (is instanceof ProcletProxyStream) { + throw new ProxyStreamException( + "Proclet stream points to another proclet stream (fd = " + fd + ")"); } + return is; } - @SuppressWarnings("unchecked") - public boolean sameStream(InputStream obj) throws ProxyStreamException { - InputStream rs = getRealStream(); - if (obj == rs) { - return true; - } else if (rs instanceof ProxyStream) { - return ((ProxyStream<InputStream>) rs).sameStream(obj); - } else if (obj instanceof ProxyStream) { - return ((ProxyStream<InputStream>) obj).sameStream(rs); - } else { - return false; + InputStream getProxiedStream(int pid) { + InputStream is = streamMap.get(pid); + if (is == null && pid != ProcletIOContext.GLOBAL_STREAM_ID) { + is = streamMap.get(ProcletIOContext.GLOBAL_STREAM_ID); } + return is; } } Modified: trunk/shell/src/shell/org/jnode/shell/proclet/ProcletProxyPrintStream.java =================================================================== --- trunk/shell/src/shell/org/jnode/shell/proclet/ProcletProxyPrintStream.java 2009-01-07 11:45:52 UTC (rev 4835) +++ trunk/shell/src/shell/org/jnode/shell/proclet/ProcletProxyPrintStream.java 2009-01-09 12:26:02 UTC (rev 4836) @@ -22,10 +22,11 @@ package org.jnode.shell.proclet; import java.io.PrintStream; +import java.util.HashMap; +import java.util.Map; import org.jnode.util.ProxyStream; import org.jnode.util.ProxyStreamException; -import org.jnode.vm.VmSystem; /** * This class provides a proxy mechanism for System.out,err. If the current @@ -37,46 +38,64 @@ */ public class ProcletProxyPrintStream extends AbstractProxyPrintStream implements ProcletProxyStream<PrintStream> { + + private Map<Integer, PrintStream> streamMap; + private final int fd; - public ProcletProxyPrintStream(int fd) { + /** + * Construct a proxy print stream with 'out' as the initial global stream. + * + * @param proxy + * @param ps + * @param pid + */ + public ProcletProxyPrintStream(PrintStream ps, int fd) { super(); + if (ps == null) { + throw new IllegalArgumentException("null stream"); + } this.fd = fd; + streamMap = new HashMap<Integer, PrintStream>(); + streamMap.put(ProcletIOContext.GLOBAL_STREAM_ID, ps); } - + /** + * Construct a proxy print stream based on the state of the supplied proxy. + * The new proxy has all entries of the existing one except that the entry + * for pid is set / reset to in. + * + * @param proxy + * @param ps + * @param pid + */ + public ProcletProxyPrintStream(ProcletProxyPrintStream proxy, PrintStream ps, + int pid) { + if (ps == null) { + throw new IllegalArgumentException("null stream"); + } + streamMap = new HashMap<Integer, PrintStream>(proxy.streamMap); + streamMap.put(pid, ps); + fd = proxy.fd; + } + + /** * This method does the work of deciding which printstream to delegate to. * * @return the PrintStream we are currently delegating to. */ private PrintStream proxiedPrintStream() throws ProxyStreamException { - ThreadGroup threadGroup = Thread.currentThread().getThreadGroup(); - if (threadGroup instanceof ProcletContext) { - try { - Object stream = ((ProcletContext) threadGroup).getStream(fd); - if (stream instanceof ProcletProxyStream) { - throw new ProxyStreamException( - "Proclet stream points to another proclet stream"); - } - if (stream instanceof ProxyStream) { - stream = ((ProxyStream<?>) stream).getRealStream(); - } - return (PrintStream) stream; - } catch (Exception ex) { - throw new ProxyStreamException("Proclet print broken for fd = " - + fd, ex); - } - } else { - switch (fd) { - case 1: - return VmSystem.getGlobalOutStream(); - case 2: - return VmSystem.getGlobalErrStream(); - default: - throw new ProxyStreamException( - "Proclet print stream broken: wrong fd = " + fd); - } + ProcletContext procletContext = ProcletContext.currentProcletContext(); + int pid = (procletContext == null) ? ProcletIOContext.GLOBAL_STREAM_ID : procletContext.getPid(); + PrintStream ps = getProxiedStream(pid); + if (ps == null) { + throw new ProxyStreamException( + "Proclet stream not set (fd = " + fd + ")"); + } else if (ps instanceof ProcletProxyStream) { + throw new ProxyStreamException( + "Proclet stream points to another proclet stream (fd = " + fd + ")"); } + return ps; } @SuppressWarnings("unchecked") @@ -101,18 +120,12 @@ return proxiedPrintStream(); } - @SuppressWarnings("unchecked") - public boolean sameStream(PrintStream obj) throws ProxyStreamException { - PrintStream rs = getRealStream(); - if (obj == rs) { - return true; - } else if (rs instanceof ProxyStream) { - return ((ProxyStream<PrintStream>) rs).sameStream(obj); - } else if (obj instanceof ProxyStream) { - return ((ProxyStream<PrintStream>) obj).sameStream(rs); - } else { - return false; + PrintStream getProxiedStream(int pid) { + PrintStream ps = streamMap.get(pid); + if (ps == null && pid != ProcletIOContext.GLOBAL_STREAM_ID) { + ps = streamMap.get(ProcletIOContext.GLOBAL_STREAM_ID); } + return ps; } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |