I'm on vacation so I haven't had a chance to look at this patch.

Beware that there are issues with nonblocking io and select().  While a
SocketChannel is being select()ed, it *must* be in nonblocking mode.  I
was thinking about implementing fcntl for nonblocking io, but the
problem is what if while one thread is select()ing on a socket, another
sets the socket blocking?  Either we have to block the fcntl until the
select completes or we have to do some weird threading delay-set magic.

Granted there might not be one single instance of something like this
happening, but then again there might.

Evan

Ola Bini wrote:
> 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
>   




_______________________________________________
Jruby-devel mailing list
Jruby-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jruby-devel

Reply via email to