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
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/jruby-devel
>
_______________________________________________
Jruby-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jruby-devel