Hi

I've managed to fix a working fcntl implementation that sets nonblocking io when asked to. Patch is attached.
This makes a simple daytime server work flawlessly.

When I scale this up and try something like this:

require 'webrick'
include WEBrick

s = HTTPServer.new(
  :Port            => 2000,
  :DocumentRoot    => %q(d:\web\htdocs)
)

trap("INT"){ s.shutdown }
s.start

... we get into trouble again. Guess what it is?
java.lang.RuntimeException: java.lang.InterruptedException
        at org.jruby.RubyThread.criticalizeOrDieIfKilled(RubyThread.java:293)
        at org.jruby.RubyThread.pollThreadEvents(RubyThread.java:278)
        at 
org.jruby.runtime.ThreadContext.pollThreadEvents(ThreadContext.java:471)
        at 
org.jruby.evaluator.EvaluationState.executeNext(EvaluationState.java:257)
        at org.jruby.evaluator.EvaluationState.begin(EvaluationState.java:297)
at org.jruby.internal.runtime.methods.EvaluateCallable.internalCall(EvaluateCallable.java:67) at org.jruby.internal.runtime.methods.AbstractCallable.call(AbstractCallable.java:64)
        at org.jruby.runtime.ThreadContext.yield(ThreadContext.java:347)
        at org.jruby.runtime.Block.call(Block.java:114)
        at org.jruby.RubyProc.call(RubyProc.java:118)
        at org.jruby.RubyProc.call(RubyProc.java:104)
        at 
org.jruby.internal.runtime.RubyNativeThread.run(RubyNativeThread.java:75)
Caused by: java.lang.InterruptedException
        at java.lang.Object.wait(Native Method)
        at java.lang.Object.wait(Object.java:429)
        at org.jruby.RubyThread.waitIfCriticalized(RubyThread.java:260)
        at org.jruby.RubyThread.criticalizeOrDieIfKilled(RubyThread.java:290)
        ... 11 more


Our old friend. The server actually does work, but sillyness slow, even on a localhost. Maybe some uses of timeout here too? Doesn't seem to be in the relevant parts, actually, but there is obviously something strange going on...

Anyway, fcntl takes us one step further.

Regards
 Ola Bini
Index: src/org/jruby/runtime/builtin/meta/IOMetaClass.java
===================================================================
RCS file: 
/cvsroot/jruby/jruby/src/org/jruby/runtime/builtin/meta/IOMetaClass.java,v
retrieving revision 1.18
diff -u -r1.18 IOMetaClass.java
--- src/org/jruby/runtime/builtin/meta/IOMetaClass.java 26 May 2006 01:47:52 
-0000      1.18
+++ src/org/jruby/runtime/builtin/meta/IOMetaClass.java 13 Jun 2006 11:34:47 
-0000
@@ -95,6 +95,7 @@
                defineMethod("each_line", Arity.optional());
                defineMethod("eof", Arity.noArguments());
                defineAlias("eof?", "eof");
+               defineMethod("fcntl", Arity.twoArguments());
                defineMethod("fileno", Arity.noArguments());
                defineMethod("flush", Arity.noArguments());
                defineMethod("fsync", Arity.noArguments());
Index: src/org/jruby/RubyIO.java
===================================================================
RCS file: /cvsroot/jruby/jruby/src/org/jruby/RubyIO.java,v
retrieving revision 1.52
diff -u -r1.52 RubyIO.java
--- src/org/jruby/RubyIO.java   24 May 2006 01:34:03 -0000      1.52
+++ src/org/jruby/RubyIO.java   13 Jun 2006 11:47:55 -0000
@@ -40,6 +40,7 @@
 import java.io.OutputStream;
 import java.lang.ref.WeakReference;
 import java.nio.channels.Channel;
+import java.nio.channels.SelectableChannel;
 
 import org.jruby.runtime.builtin.IRubyObject;
 import org.jruby.util.IOHandler;
@@ -806,6 +807,31 @@
         return result;
     }
 
+    public IRubyObject fcntl(final IRubyObject cmd, final IRubyObject arg) 
throws IOException {
+        if(arg instanceof RubyNumeric) {
+            final long realCmd = ((RubyNumeric)cmd).getLongValue();
+            final long realArg = ((RubyNumeric)arg).getLongValue();
+            if(realCmd == 1L) {
+                // cmd is F_SETFL
+                boolean block = false;
+                if((realArg & IOModes.NONBLOCK) == IOModes.NONBLOCK) {
+                    block = true;
+                }
+                final Channel chn = getChannel();
+                if(chn != null && chn instanceof SelectableChannel) {
+                    try {
+                        ((SelectableChannel)chn).configureBlocking(block);
+                    } catch(final IOException e) {
+                        throw getRuntime().newIOError(e.getMessage());
+                    }
+                }         
+            }
+            return RubyFixnum.zero(getRuntime());
+        } else {
+            return getRuntime().getNil();
+        }
+    }
+
     public IRubyObject puts(IRubyObject[] args) {
        checkArgumentCount(args, 0, -1);
        
Index: src/builtin/fcntl.rb
===================================================================
RCS file: /cvsroot/jruby/jruby/src/builtin/fcntl.rb,v
retrieving revision 1.1
diff -u -r1.1 fcntl.rb
--- src/builtin/fcntl.rb        23 Nov 2005 10:55:36 -0000      1.1
+++ src/builtin/fcntl.rb        13 Jun 2006 11:42:58 -0000
@@ -0,0 +1,12 @@
+class Fcntl
+  F_SETFL = 1
+  O_RDWR = File::RDWR
+  O_TRUNC = File::TRUNC
+  O_RDONLY = File::RDONLY
+  O_EXCL = File::EXCL
+  O_ACCMODE = File::NOCTTY
+  O_NONBLOCK = File::NONBLOCK
+  O_CREAT = File::CREAT
+  O_WRONLY = File::WRONLY
+  O_APPEND = File::APPEND
+end
_______________________________________________
Jruby-devel mailing list
Jruby-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jruby-devel

Reply via email to