|
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.
|