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: 7250ae51c5f0
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 81c8c1d101d8
Choose a head ref
  • 5 commits
  • 4 files changed
  • 1 contributor

Commits on Jul 1, 2015

  1. Copy the full SHA
    db2bf39 View commit details
  2. Copy the full SHA
    d6a6654 View commit details
  3. Copy the full SHA
    af7aeff View commit details
  4. Copy the full SHA
    0a74bdd View commit details
  5. Copy the full SHA
    81c8c1d View commit details
Original file line number Diff line number Diff line change
@@ -34,9 +34,10 @@ public static abstract class ExceptionErrnoErrorPrimitiveNode extends RubiniusPr
protected final static int EFAULT = Errno.EFAULT.intValue();
protected final static int ENOTDIR = Errno.ENOTDIR.intValue();
protected final static int EINVAL = Errno.EINVAL.intValue();
protected final static int EINPROGRESS = Errno.EINPROGRESS.intValue();

public static boolean isExceptionSupported(int errno) {
return errno == EPERM || errno == ENOENT || errno == EBADF || errno == EEXIST || errno == EACCES || errno == EFAULT || errno == ENOTDIR || errno == EINVAL;
return errno == EPERM || errno == ENOENT || errno == EBADF || errno == EEXIST || errno == EACCES || errno == EFAULT || errno == ENOTDIR || errno == EINVAL || errno == EINPROGRESS;
}

public ExceptionErrnoErrorPrimitiveNode(RubyContext context, SourceSection sourceSection) {
@@ -108,6 +109,11 @@ public RubyException einval(RubyString message, int errno) {
return getContext().getCoreLibrary().errnoError(errno, this);
}

@Specialization(guards = "errno == EINPROGRESS")
public RubyException einprogress(RubyString message, int errno) {
return getContext().getCoreLibrary().errnoError(errno, this);
}

@TruffleBoundary
@Specialization(guards = "!isExceptionSupported(errno)")
public RubyException unsupported(Object message, int errno) {
Original file line number Diff line number Diff line change
@@ -46,6 +46,7 @@
import com.oracle.truffle.api.source.SourceSection;
import jnr.constants.platform.Errno;
import jnr.constants.platform.Fcntl;
import jnr.ffi.Pointer;
import jnr.ffi.byref.IntByReference;
import org.jruby.RubyEncoding;
import org.jruby.truffle.nodes.RubyGuards;
@@ -312,6 +313,62 @@ public RubyBasicObject ensureOpen(VirtualFrame frame, RubyBasicObject file) {

}

@RubiniusPrimitive(name = "io_read_if_available")
public static abstract class IOReadIfAvailableNode extends RubiniusPrimitiveNode {

private static final FDSetFactory fdSetFactory = FDSetFactoryFactory.create();

public IOReadIfAvailableNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@TruffleBoundary
@Specialization
public Object readIfAvailable(RubyBasicObject file, int numberOfBytes) {
// Taken from Rubinius's IO::read_if_available.

if (numberOfBytes == 0) {
return StringNodes.createEmptyString(getContext().getCoreLibrary().getStringClass());
}

final int fd = getDescriptor(file);

final FDSet fdSet = fdSetFactory.create();
fdSet.set(fd);

final Pointer timeout = jnr.ffi.Runtime.getSystemRuntime().getMemoryManager().allocateDirect(8 * 2); // Needs to be two longs.
timeout.putLong(0, 0);
timeout.putLong(8, 0);

final int res = nativeSockets().select(fd + 1, fdSet.getPointer(), PointerNodes.NULL_POINTER, PointerNodes.NULL_POINTER, timeout);

if (res == 0) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().errnoError(Errno.EAGAIN.intValue(), this));
}

if (res < 0) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().errnoError(getContext().getPosix().errno(), this));
}

final byte[] bytes = new byte[numberOfBytes];
final int bytesRead = getContext().getPosix().read(fd, bytes, numberOfBytes);

if (bytesRead == -1) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().errnoError(getContext().getPosix().errno(), this));
}

if (bytesRead == 0) {
return StringNodes.createEmptyString(getContext().getCoreLibrary().getStringClass());
}

return StringNodes.createString(getContext().getCoreLibrary().getStringClass(), bytes);
}

}

@RubiniusPrimitive(name = "io_reopen")
public static abstract class IOReopenPrimitiveNode extends RubiniusPrimitiveNode {

@@ -601,6 +658,40 @@ public Integer block() throws InterruptedException {
ArrayNodes.fromObjects(getContext().getCoreLibrary().getArrayClass()));
}

@TruffleBoundary
@Specialization(guards = { "isNil(readables)", "isRubyArray(writables)", "isNil(errorables)" })
public Object selectNilReadables(RubyBasicObject readables, RubyBasicObject writables, RubyBasicObject errorables, int timeout) {
final Object[] writableObjects = ArrayNodes.slowToArray(writables);
final int[] writableFds = getFileDescriptors(writables);

final FDSet writableSet = fdSetFactory.create();

for (int fd : writableFds) {
writableSet.set(fd);
}

final int result = getContext().getThreadManager().runOnce(new ThreadManager.BlockingActionWithoutGlobalLock<Integer>() {
@Override
public Integer block() throws InterruptedException {
return nativeSockets().select(
max(writableFds) + 1,
PointerNodes.NULL_POINTER,
writableSet.getPointer(),
PointerNodes.NULL_POINTER,
PointerNodes.NULL_POINTER);
}
});

if (result == -1) {
return nil();
}

return ArrayNodes.fromObjects(getContext().getCoreLibrary().getArrayClass(),
ArrayNodes.fromObjects(getContext().getCoreLibrary().getArrayClass()),
getSetObjects(writableObjects, writableFds, writableSet),
ArrayNodes.fromObjects(getContext().getCoreLibrary().getArrayClass()));
}

private int[] getFileDescriptors(RubyBasicObject fileDescriptorArray) {
assert RubyGuards.isRubyArray(fileDescriptorArray);

Original file line number Diff line number Diff line change
@@ -838,6 +838,29 @@ public int getaddrinfo(RubyString hostName, RubyString serviceName, RubyBasicObj
PointerNodes.getPointer(resultsPointer));
}

@Specialization(guards = { "isNil(serviceName)", "isRubyPointer(hintsPointer)", "isRubyPointer(resultsPointer)" })
public int getaddrinfo(RubyString hostName, RubyBasicObject serviceName, RubyBasicObject hintsPointer, RubyBasicObject resultsPointer) {
return nativeSockets().getaddrinfo(
StringNodes.getByteList(hostName),
null,
PointerNodes.getPointer(hintsPointer),
PointerNodes.getPointer(resultsPointer));
}

}

@CoreMethod(names = "_connect", isModuleFunction = true, required = 3, lowerFixnumParameters = {0, 2})
public abstract static class ConnectNode extends CoreMethodArrayArgumentsNode {

public ConnectNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Specialization(guards = "isRubyPointer(address)")
public int connect(int socket, RubyBasicObject address, int address_len) {
return nativeSockets().connect(socket, PointerNodes.getPointer(address), address_len);
}

}

@CoreMethod(names = "freeaddrinfo", isModuleFunction = true, required = 1)
Original file line number Diff line number Diff line change
@@ -105,4 +105,11 @@ public interface NativeSockets {

int getsockname(int socket, Pointer address, Pointer address_len);

/**
* int connect(int sockfd, const struct sockaddr *addr,
* socklen_t addrlen);
*/

int connect(int socket, Pointer address, int address_len);

}