Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: f4e7faabc3d5
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 0558663aff9a
Choose a head ref
  • 7 commits
  • 883 files changed
  • 1 contributor

Commits on Dec 28, 2015

  1. Implement more _nonblock forms and remove ugly hacks from MRI.

    See https://bugs.ruby-lang.org/issues/11339 for said hacks and
    my arguments against them.
    headius committed Dec 28, 2015
    Copy the full SHA
    b27a2b0 View commit details
  2. Copy the full SHA
    b77dc0e View commit details
  3. Update tests from MRI 2.3.0.

    headius committed Dec 28, 2015
    Copy the full SHA
    ae5aaf6 View commit details
  4. Copy the full SHA
    38092b1 View commit details
  5. Copy the full SHA
    cfa79ff View commit details
  6. Copy the full SHA
    bd29416 View commit details
  7. Copy the full SHA
    0558663 View commit details
Showing 883 changed files with 16,714 additions and 5,852 deletions.
24 changes: 6 additions & 18 deletions core/src/main/java/org/jruby/RubyIO.java
Original file line number Diff line number Diff line change
@@ -1337,18 +1337,12 @@ public IRubyObject write_nonblock(ThreadContext context, IRubyObject[] argv) {
Ruby runtime = context.runtime;
IRubyObject str;
IRubyObject opts = context.nil;
boolean no_exceptions = false;

int argc = Arity.checkArgumentCount(context, argv, 1, 2);
if (argc == 2) {
opts = argv[1].convertToHash();
}
str = argv[0];
boolean exception = ArgsUtil.extractKeywordArg(context, "exception", argv) != runtime.getFalse();

if (!opts.isNil() && runtime.getFalse() == ((RubyHash)opts).op_aref(context, runtime.newSymbol("exception")))
no_exceptions = true;
str = argv[0];

return ioWriteNonblock(context, runtime, str, no_exceptions);
return ioWriteNonblock(context, runtime, str, !exception);
}

// MRI: io_write_nonblock
@@ -2776,18 +2770,12 @@ public IRubyObject read_nonblock(ThreadContext context, IRubyObject[] args) {
// MRI: io_read_nonblock
public IRubyObject doReadNonblock(ThreadContext context, IRubyObject[] args, boolean useException) {
final Ruby runtime = context.runtime;
boolean noException = !useException;

IRubyObject opts = ArgsUtil.getOptionsArg(runtime, args);

if ( ! opts.isNil() &&
runtime.getFalse() == ((RubyHash) opts).op_aref(context, runtime.newSymbol("exception")) ) {
noException = true;
}
boolean exception = ArgsUtil.extractKeywordArg(context, "exception", args) != runtime.getFalse();

IRubyObject ret = getPartial(context, args, true, noException);
IRubyObject ret = getPartial(context, args, true, !exception);

return ret.isNil() ? nonblockEOF(runtime, noException) : ret;
return ret.isNil() ? nonblockEOF(runtime, !exception) : ret;
}

// MRI: io_nonblock_eof(VALUE opts)
9 changes: 9 additions & 0 deletions core/src/main/java/org/jruby/RubyKernel.java
Original file line number Diff line number Diff line change
@@ -1177,6 +1177,15 @@ public static IRubyObject warn(ThreadContext context, IRubyObject recv, IRubyObj
return runtime.getNil();
}

@JRubyMethod(module = true, required = 1, rest = true, visibility = PRIVATE)
public static IRubyObject warn(ThreadContext context, IRubyObject recv, IRubyObject... messages) {
Ruby runtime = context.runtime;

for (IRubyObject message : messages) warn(context, recv, message);

return runtime.getNil();
}

@JRubyMethod(module = true, visibility = PRIVATE)
public static IRubyObject set_trace_func(ThreadContext context, IRubyObject recv, IRubyObject trace_func, Block block) {
if (trace_func.isNil()) {
25 changes: 25 additions & 0 deletions core/src/main/java/org/jruby/ast/util/ArgsUtil.java
Original file line number Diff line number Diff line change
@@ -152,6 +152,10 @@ public static IRubyObject getOptionsArg(Ruby runtime, IRubyObject... args) {
return runtime.getNil();
}

public static IRubyObject getOptionsArg(Ruby runtime, IRubyObject arg) {
return TypeConverter.checkHashType(runtime, arg);
}

/**
* Check that the given kwargs hash doesn't contain any keys other than those which are given as valid.
* @param context The context to execute in
@@ -194,4 +198,25 @@ public static IRubyObject[] extractKeywordArgs(ThreadContext context, IRubyObjec
return null;
}
}

public static IRubyObject extractKeywordArg(ThreadContext context, String keyword, IRubyObject arg) {
IRubyObject opts = ArgsUtil.getOptionsArg(context.runtime, arg);

if (!opts.isNil()) return ((RubyHash) opts).op_aref(context, context.runtime.newSymbol(keyword));

return context.nil;
}

public static IRubyObject extractKeywordArg(ThreadContext context, String keyword, IRubyObject... args) {
IRubyObject opts = ArgsUtil.getOptionsArg(context.runtime, args);

if (!opts.isNil()) return ((RubyHash) opts).op_aref(context, context.runtime.newSymbol(keyword));

return context.nil;
}

public static IRubyObject extractArg(int index, IRubyObject _default, IRubyObject... args) {
if (index < args.length) return args[index];
return _default;
}
}
52 changes: 25 additions & 27 deletions core/src/main/java/org/jruby/ext/socket/RubyBasicSocket.java
Original file line number Diff line number Diff line change
@@ -54,6 +54,7 @@
import org.jruby.RubySymbol;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.ast.util.ArgsUtil;
import org.jruby.ext.fcntl.FcntlLibrary;
import org.jruby.platform.Platform;
import org.jruby.runtime.Arity;
@@ -199,54 +200,51 @@ private IRubyObject recv(ThreadContext context, IRubyObject length,

@JRubyMethod
public IRubyObject recv_nonblock(ThreadContext context, IRubyObject length) {
return recv_nonblock(context, length, null, null);
return recv_nonblock(context, length, context.nil, context.nil, false);
}

@JRubyMethod(required = 2, optional = 1) // (length) required = 1 handled above
@JRubyMethod(required = 1, optional = 3) // (length) required = 1 handled above
public IRubyObject recv_nonblock(ThreadContext context, IRubyObject[] args) {
IRubyObject length; RubyString str; IRubyObject flags;
Ruby runtime = context.runtime;
int argc = args.length;
IRubyObject opts = ArgsUtil.getOptionsArg(context.runtime, args);
if (!opts.isNil()) argc--;

switch (args.length) {
IRubyObject length = context.nil;
IRubyObject flags = length;
IRubyObject str = length;

switch (argc) {
case 3:
length = args[0];
str = (RubyString) args[1];
flags = args[2].convertToHash();
break;
str = args[3];
case 2:
length = args[0];
flags = TypeConverter.checkHashType(context.runtime, args[1]);
str = flags.isNil() ? (RubyString) args[1] : null;
break;
flags = args[2];
case 1:
length = args[0];
str = null; flags = null;
break;
default:
length = context.nil;
str = null; flags = null;
length = args[1];
}

return recv_nonblock(context, length, str, flags);
}
boolean exception = ArgsUtil.extractKeywordArg(context, "exception", opts) != runtime.getFalse();

@Deprecated
public IRubyObject recv_nonblock(ThreadContext context, IRubyObject length, IRubyObject flags) {
return recv_nonblock(context, new IRubyObject[] { length, flags });
return recv_nonblock(context, length, flags, str, exception);
}

private IRubyObject recv_nonblock(ThreadContext context, IRubyObject length,
RubyString str, IRubyObject flags) {
protected IRubyObject recv_nonblock(ThreadContext context, IRubyObject length,
IRubyObject flags, IRubyObject str, boolean ex) {
Ruby runtime = context.runtime;

// TODO: implement flags
final ByteBuffer buffer = ByteBuffer.allocate(RubyNumeric.fix2int(length));

ByteList bytes = doReceiveNonblock(context, buffer);

if (bytes == null) {
if (!ex) return runtime.newSymbol("wait_readable");
throw context.runtime.newErrnoEAGAINReadableError("recvfrom(2)");
}

if (str != null) {
str.setValue(bytes);
if (str != null && !str.isNil()) {
str = str.convertToString();
((RubyString)str).setValue(bytes);
return str;
}
return RubyString.newString(context.runtime, bytes);
21 changes: 15 additions & 6 deletions core/src/main/java/org/jruby/ext/socket/RubyServerSocket.java
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@
import org.jruby.RubyFixnum;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.ast.util.ArgsUtil;
import org.jruby.common.IRubyWarnings;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
@@ -125,12 +126,17 @@ public IRubyObject bind(ThreadContext context, IRubyObject addr, IRubyObject bac

@JRubyMethod()
public IRubyObject accept(ThreadContext context) {
return doAccept(context, getChannel());
return doAccept(context, getChannel(), true);
}

@JRubyMethod()
public IRubyObject accept_nonblock(ThreadContext context) {
return doAcceptNonblock(context, getChannel());
return accept_nonblock(context, context.nil);
}

@JRubyMethod()
public IRubyObject accept_nonblock(ThreadContext context, IRubyObject opts) {
return doAcceptNonblock(context, getChannel(), ArgsUtil.extractKeywordArg(context, "exception", opts) != context.runtime.getFalse());
}

protected ChannelFD initChannelFD(Ruby runtime) {
@@ -151,7 +157,7 @@ protected ChannelFD initChannelFD(Ruby runtime) {
}
}

private RubyArray doAcceptNonblock(ThreadContext context, Channel channel) {
private IRubyObject doAcceptNonblock(ThreadContext context, Channel channel, boolean ex) {
try {
if (channel instanceof SelectableChannel) {
SelectableChannel selectable = (SelectableChannel)channel;
@@ -162,8 +168,9 @@ private RubyArray doAcceptNonblock(ThreadContext context, Channel channel) {
try {
selectable.configureBlocking(false);

RubySocket socket = doAccept(context, channel);
SocketChannel socketChannel = (SocketChannel)socket.getChannel();
IRubyObject socket = doAccept(context, channel, ex);
if (!(socket instanceof RubySocket)) return socket;
SocketChannel socketChannel = (SocketChannel)((RubySocket)socket).getChannel();
InetSocketAddress addr = (InetSocketAddress)socketChannel.socket().getRemoteSocketAddress();

return context.runtime.newArray(
@@ -183,7 +190,7 @@ private RubyArray doAcceptNonblock(ThreadContext context, Channel channel) {
}
}

private RubySocket doAccept(ThreadContext context, Channel channel) {
private IRubyObject doAccept(ThreadContext context, Channel channel, boolean ex) {
Ruby runtime = context.runtime;

try {
@@ -196,6 +203,7 @@ private RubySocket doAccept(ThreadContext context, Channel channel) {
// This appears to be undocumented in JDK; null as a sentinel value
// for a nonblocking accept with nothing available. We raise for Ruby.
// indicates that no connection is available in non-blocking mode
if (!ex) return runtime.newSymbol("wait_readable");
throw runtime.newErrnoEAGAINReadableError("accept(2) would block");
}

@@ -208,6 +216,7 @@ private RubySocket doAccept(ThreadContext context, Channel channel) {
}
catch (IllegalBlockingModeException e) {
// indicates that no connection is available in non-blocking mode
if (!ex) return runtime.newSymbol("wait_readable");
throw runtime.newErrnoEAGAINReadableError("accept(2) would block");
}
catch (IOException e) {
47 changes: 33 additions & 14 deletions core/src/main/java/org/jruby/ext/socket/RubySocket.java
Original file line number Diff line number Diff line change
@@ -67,6 +67,7 @@
import org.jruby.RubyModule;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.ast.util.ArgsUtil;
import org.jruby.exceptions.RaiseException;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
@@ -190,9 +191,18 @@ public IRubyObject initialize(ThreadContext context, IRubyObject domain, IRubyOb

@JRubyMethod()
public IRubyObject connect_nonblock(ThreadContext context, IRubyObject arg) {
return connect_nonblock(context, arg, context.nil);
}

@JRubyMethod()
public IRubyObject connect_nonblock(ThreadContext context, IRubyObject arg, IRubyObject opts) {
Ruby runtime = context.runtime;

SocketAddress addr = addressForChannel(context, arg);

doConnectNonblock(context, getChannel(), addr);
boolean exception = ArgsUtil.extractKeywordArg(context, "exception", opts) != runtime.getFalse();

doConnectNonblock(context, getChannel(), addr, exception);

return RubyFixnum.zero(context.runtime);
}
@@ -201,7 +211,7 @@ public IRubyObject connect_nonblock(ThreadContext context, IRubyObject arg) {
public IRubyObject connect(ThreadContext context, IRubyObject arg) {
SocketAddress addr = addressForChannel(context, arg);

doConnect(context, getChannel(), addr);
doConnect(context, getChannel(), addr, true);

return RubyFixnum.zero(context.runtime);
}
@@ -238,9 +248,9 @@ public IRubyObject recvfrom_nonblock(ThreadContext context, IRubyObject length)
return super.recv_nonblock(context, length);
}

@JRubyMethod
public IRubyObject recvfrom_nonblock(ThreadContext context, IRubyObject length, IRubyObject flags) {
return super.recv_nonblock(context, length, flags);
@JRubyMethod(required = 1, optional = 3)
public IRubyObject recvfrom_nonblock(ThreadContext context, IRubyObject[] args) {
return super.recv_nonblock(context, args);
}

@JRubyMethod(notImplemented = true)
@@ -253,6 +263,11 @@ public IRubyObject accept(ThreadContext context) {
throw SocketUtils.sockerr(context.runtime, JRUBY_SERVER_SOCKET_ERROR);
}

@JRubyMethod(notImplemented = true, optional = 1)
public IRubyObject accept_nonblock(ThreadContext context, IRubyObject[] args) {
throw SocketUtils.sockerr(context.runtime, JRUBY_SERVER_SOCKET_ERROR);
}

@JRubyMethod(meta = true)
public static IRubyObject gethostname(ThreadContext context, IRubyObject recv) {
return SocketUtils.gethostname(context);
@@ -464,7 +479,7 @@ private void initDomain(Ruby runtime, IRubyObject domain) {
soProtocolFamily = ProtocolFamily.valueOf("PF" + name.substring(2));
}

private void doConnectNonblock(ThreadContext context, Channel channel, SocketAddress addr) {
private IRubyObject doConnectNonblock(ThreadContext context, Channel channel, SocketAddress addr, boolean ex) {
if ( ! (channel instanceof SelectableChannel) ) {
throw context.runtime.newErrnoENOPROTOOPTError();
}
@@ -476,7 +491,7 @@ private void doConnectNonblock(ThreadContext context, Channel channel, SocketAdd
selectable.configureBlocking(false);

try {
doConnect(context, channel, addr);
return doConnect(context, channel, addr, ex);

} finally {
selectable.configureBlocking(oldBlocking);
@@ -492,27 +507,23 @@ private void doConnectNonblock(ThreadContext context, Channel channel, SocketAdd
}
}

protected void doConnect(ThreadContext context, Channel channel, SocketAddress addr) {
protected IRubyObject doConnect(ThreadContext context, Channel channel, SocketAddress addr, boolean ex) {
Ruby runtime = context.runtime;

try {
boolean result = true;
if (channel instanceof SocketChannel) {
SocketChannel socket = (SocketChannel) channel;
boolean result;

if (socket.isConnectionPending()) {
// connection initiated but not finished
result = socket.finishConnect();
} else {
result = socket.connect(addr);
}

if ( ! result ) {
throw runtime.newErrnoEINPROGRESSWritableError();
}
}
else if (channel instanceof UnixSocketChannel) {
((UnixSocketChannel) channel).connect((UnixSocketAddress) addr);
result = ((UnixSocketChannel) channel).connect((UnixSocketAddress) addr);

}
else if (channel instanceof DatagramChannel) {
@@ -521,8 +532,14 @@ else if (channel instanceof DatagramChannel) {
else {
throw runtime.newErrnoENOPROTOOPTError();
}

if ( ! result ) {
if (!ex) return runtime.newSymbol("wait_readable");
throw runtime.newErrnoEINPROGRESSWritableError();
}
}
catch (AlreadyConnectedException e) {
if (!ex) return runtime.newFixnum(0);
throw runtime.newErrnoEISCONNError();
}
catch (ConnectionPendingException e) {
@@ -540,6 +557,8 @@ else if (channel instanceof DatagramChannel) {
catch (IllegalArgumentException e) {
throw sockerr(runtime, e.getMessage(), e);
}

return runtime.newFixnum(0);
}

protected void doBind(ThreadContext context, Channel channel, InetSocketAddress iaddr) {
Loading