On Thu, 29 Jun 2006, Charles O Nutter defenestrated me:
>
> Whee!
I needed to do a surprising additional number of things to
get rails silence_stderr working with this patch. Here is a break-
down:
1. reopen with string as first arg should retain permissions/modes
of IO it is reopening. I believe this has to be right.
2. dup should retain dup'd objects permissions/modes. This also
seems like a for sure thing.
3. reopen needed same /dev/null check that RubyFile has in reopen.
As hacky as hacky gets.
4. IOHandlerUnseekable now refuses to close System.out and System.err.
This is also a hack. The solution involves much too much stuff
to be safe right now. Really a io.dup should clone the underlying
IOHandler. If multiple IO's point to same underlying stream
then a close should not really close the underlying stream.
I believe this is consistent with C FILE* and friends (C Ruby
semantics I think rely on FILE* and friends)?
Please look this over. I would like to include this for 0.9.0
since it makes Rails commands that perform command checks work without
needing to patch Rails.
-Tom
--
+ http://www.tc.umn.edu/~enebo +---- mailto:[EMAIL PROTECTED] ----+
| Thomas E Enebo, Protagonist | "Luck favors the prepared |
| | mind." -Louis Pasteur |
Index: org/jruby/RubyFile.java
===================================================================
RCS file: /cvsroot/jruby/jruby/src/org/jruby/RubyFile.java,v
retrieving revision 1.40
diff -u -r1.40 RubyFile.java
--- org/jruby/RubyFile.java 30 May 2006 17:52:48 -0000 1.40
+++ org/jruby/RubyFile.java 30 Jun 2006 02:59:35 -0000
@@ -44,6 +44,7 @@
import org.jruby.exceptions.RaiseException;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.IOHandler;
+import org.jruby.util.IOHandlerNull;
import org.jruby.util.IOHandlerSeekable;
import org.jruby.util.IOHandlerUnseekable;
import org.jruby.util.IOModes;
@@ -105,9 +106,13 @@
public void openInternal(String newPath, IOModes newModes) {
this.path = newPath;
this.modes = newModes;
-
+
try {
- handler = new IOHandlerSeekable(getRuntime(), newPath, newModes);
+ if (newPath.equals("/dev/null")) {
+ handler = new IOHandlerNull(getRuntime(), newModes);
+ } else {
+ handler = new IOHandlerSeekable(getRuntime(), newPath,
newModes);
+ }
registerIOHandler(handler);
} catch (InvalidValueException e) {
Index: org/jruby/RubyIO.java
===================================================================
RCS file: /cvsroot/jruby/jruby/src/org/jruby/RubyIO.java,v
retrieving revision 1.55
diff -u -r1.55 RubyIO.java
--- org/jruby/RubyIO.java 28 Jun 2006 02:25:51 -0000 1.55
+++ org/jruby/RubyIO.java 30 Jun 2006 02:59:37 -0000
@@ -45,6 +45,7 @@
import org.jruby.util.IOHandler;
import org.jruby.util.IOHandlerJavaIO;
import org.jruby.util.IOHandlerNio;
+import org.jruby.util.IOHandlerNull;
import org.jruby.util.IOHandlerProcess;
import org.jruby.util.IOHandlerSeekable;
import org.jruby.util.IOHandlerUnseekable;
@@ -333,21 +334,29 @@
registerIOHandler(handler);
} else if (args[0].isKindOf(getRuntime().getClass("String"))) {
String path = ((RubyString) args[0]).toString();
- String mode = "r";
+ IOModes newModes = null;
+
if (args.length > 1) {
if (!args[1].isKindOf(getRuntime().getClass("String"))) {
throw getRuntime().newTypeError(args[1],
getRuntime().getClass("String"));
}
- mode = ((RubyString) args[1]).toString();
+ newModes = new IOModes(getRuntime(), ((RubyString)
args[1]).toString());
}
try {
if (handler != null) {
close();
}
- modes = new IOModes(getRuntime(), mode);
- handler = new IOHandlerSeekable(getRuntime(), path, modes);
+
+ if (newModes != null) {
+ modes = newModes;
+ }
+ if ("/dev/null".equals(path)) {
+ handler = new IOHandlerNull(getRuntime(), modes);
+ } else {
+ handler = new IOHandlerSeekable(getRuntime(), path,
modes);
+ }
registerIOHandler(handler);
} catch (IOHandler.InvalidValueException e) {
@@ -743,6 +752,7 @@
// copy of the handler. In fact, ruby 1.8 must do this as the cloned
// resource is in fact a different fileno. What is clone for again?
io.handler = handler;
+ io.modes = (IOModes) modes.clone();
return io;
}
Index: org/jruby/util/IOHandlerUnseekable.java
===================================================================
RCS file: /cvsroot/jruby/jruby/src/org/jruby/util/IOHandlerUnseekable.java,v
retrieving revision 1.16
diff -u -r1.16 IOHandlerUnseekable.java
--- org/jruby/util/IOHandlerUnseekable.java 24 May 2006 01:34:04 -0000
1.16
+++ org/jruby/util/IOHandlerUnseekable.java 30 Jun 2006 02:59:38 -0000
@@ -163,7 +163,15 @@
}
if (modes.isWriteable()) {
- output.close();
+ // Fixme: Only close underlying stream if it is not shared by
another IO.
+ // HACK: We do not close these streams so that Rails
silence_stderr will work.
+ // The real problem is that when silense_stderr clones STDERR,
we do not actually
+ // clone the handler AND get a new fileno. The importance of
this is coupled
+ // with the above Fixme, that we need to make sure we only
close underlying streams
+ // that are not shared by multiple IOHandlers (at least I
believe this to be true).
+ if (output != System.out && output != System.err) {
+ output.close();
+ }
}
}
Index: org/jruby/util/IOModes.java
===================================================================
RCS file: /cvsroot/jruby/jruby/src/org/jruby/util/IOModes.java,v
retrieving revision 1.11
diff -u -r1.11 IOModes.java
--- org/jruby/util/IOModes.java 22 Jun 2006 02:11:16 -0000 1.11
+++ org/jruby/util/IOModes.java 30 Jun 2006 02:59:38 -0000
@@ -56,6 +56,10 @@
this.runtime = runtime;
}
+ public Object clone() {
+ return new IOModes(runtime, modes);
+ }
+
public IOModes(IRuby runtime, String modesString) {
this(runtime, convertModesStringToModesInt(runtime, modesString));
}
Index: org/jruby/util/IOHandlerNull.java
===================================================================
RCS file: org/jruby/util/IOHandlerNull.java
diff -N org/jruby/util/IOHandlerNull.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ org/jruby/util/IOHandlerNull.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,101 @@
+package org.jruby.util;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.nio.channels.FileChannel;
+
+import org.jruby.IRuby;
+
+public class IOHandlerNull extends IOHandler {
+
+ public IOHandlerNull(IRuby runtime, IOModes modes) {
+ super(runtime);
+
+ this.modes = modes;
+ }
+
+ public FileChannel getFileChannel() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String gets(String separatorString) throws IOException,
+ BadDescriptorException, EOFException {
+ throw new EOFException();
+ }
+
+ public String getsEntireStream() throws IOException,
+ BadDescriptorException, EOFException {
+ throw new EOFException();
+ }
+
+ public String read(int number) throws IOException, BadDescriptorException,
+ EOFException {
+ throw new EOFException();
+ }
+
+ public int write(String string) throws IOException, BadDescriptorException
{
+ return string.length();
+ }
+
+ public int getc() throws IOException, BadDescriptorException, EOFException
{
+ throw new EOFException();
+ }
+
+ public void ungetc(int c) {
+ }
+
+ public void putc(int c) throws IOException, BadDescriptorException {
+ }
+
+ public String sysread(int number) throws IOException,
+ BadDescriptorException, EOFException {
+ throw new EOFException();
+ }
+
+ public int syswrite(String buf) throws IOException, BadDescriptorException
{
+ return buf.length();
+ }
+
+ public IOHandler cloneIOHandler() throws IOException, PipeException,
+ InvalidValueException {
+ return null;
+ }
+
+ public void close() throws IOException, BadDescriptorException {
+ }
+
+ public void flush() throws IOException, BadDescriptorException {
+ }
+
+ public void sync() throws IOException, BadDescriptorException {
+ }
+
+ public boolean isEOF() throws IOException, BadDescriptorException {
+ return true;
+ }
+
+ public int pid() {
+ return 0;
+ }
+
+ public long pos() throws IOException, PipeException {
+ return 0;
+ }
+
+ protected void resetByModes(IOModes newModes) throws IOException,
+ InvalidValueException {
+ }
+
+ public void rewind() throws IOException, PipeException,
+ InvalidValueException {
+ }
+
+ public void seek(long offset, int type) throws IOException, PipeException,
+ InvalidValueException {
+ }
+
+ public void truncate(long newLength) throws IOException, PipeException {
+ }
+
+}
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Jruby-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jruby-devel