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: 232ab4366b02
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: a7427a8713c6
Choose a head ref
  • 9 commits
  • 11 files changed
  • 1 contributor

Commits on Feb 22, 2016

  1. Copy the full SHA
    280fcb0 View commit details
  2. Copy the full SHA
    52caf91 View commit details
  3. Implement Process.exec.

    headius committed Feb 22, 2016
    Copy the full SHA
    348c267 View commit details
  4. Copy the full SHA
    b222441 View commit details
  5. Clean up imports.

    headius committed Feb 22, 2016
    Copy the full SHA
    49e528f View commit details
  6. Use recursive logic for Struct hash calculation.

    Fixes a couple MRI TestStruct tests.
    headius committed Feb 22, 2016
    Copy the full SHA
    d112a3f View commit details
  7. Apply change from MRI r45822 to force offset.

    Does not fix any issues unfortunately. Expected to fix test
    committed with that change in MRI but we're still missing
    something.
    headius committed Feb 22, 2016
    Copy the full SHA
    d9c59a6 View commit details
  8. Copy the full SHA
    19001e7 View commit details
  9. Copy the full SHA
    a7427a8 View commit details
267 changes: 259 additions & 8 deletions core/src/main/java/org/jruby/RubyProcess.java
Original file line number Diff line number Diff line change
@@ -29,6 +29,8 @@
***** END LICENSE BLOCK *****/
package org.jruby;

import jnr.constants.platform.RLIM;
import jnr.constants.platform.RLIMIT;
import jnr.constants.platform.Signal;
import jnr.constants.platform.Sysconf;
import jnr.ffi.byref.IntByReference;
@@ -39,7 +41,6 @@
import org.jruby.anno.JRubyModule;
import jnr.posix.POSIX;
import org.jruby.platform.Platform;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.BlockCallback;
import org.jruby.runtime.CallBlock;
@@ -49,13 +50,14 @@
import static org.jruby.runtime.Visibility.*;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.invokedynamic.MethodNames;
import org.jruby.runtime.marshal.CoreObjectType;
import org.jruby.util.ShellLauncher;
import org.jruby.exceptions.RaiseException;
import org.jruby.util.TypeConverter;
import org.jruby.util.io.PopenExecutor;
import org.jruby.util.io.PosixShim;

import static org.jruby.runtime.Helpers.invokedynamic;
import static org.jruby.runtime.invokedynamic.MethodNames.OP_EQUAL;
import static org.jruby.util.WindowsFFI.kernel32;
import static org.jruby.util.WindowsFFI.Kernel32.*;

@@ -93,7 +95,10 @@ public static RubyModule createProcessModule(Ruby runtime) {

runtime.loadConstantSet(process, jnr.constants.platform.PRIO.class);
runtime.loadConstantSet(process, jnr.constants.platform.RLIM.class);
runtime.loadConstantSet(process, jnr.constants.platform.RLIMIT.class);
for (RLIMIT r : RLIMIT.values()) {
if (!r.defined()) continue;
process.defineConstant(r.name(), runtime.newFixnum(r.intValue()));
}

process.defineConstant("WNOHANG", runtime.newFixnum(1));
process.defineConstant("WUNTRACED", runtime.newFixnum(2));
@@ -596,9 +601,250 @@ public static IRubyObject groups(IRubyObject recv) {
return ary;
}

@JRubyMethod(name = "setrlimit", rest = true, module = true, visibility = PRIVATE)
public static IRubyObject setrlimit(IRubyObject recv, IRubyObject[] args) {
throw recv.getRuntime().newNotImplementedError("Process#setrlimit not yet implemented");
@JRubyMethod(name = "setrlimit", module = true, visibility = PRIVATE)
public static IRubyObject setrlimit(ThreadContext context, IRubyObject recv, IRubyObject resource, IRubyObject rlimCur) {
return setrlimit(context, recv, resource, rlimCur, context.nil);
}

@JRubyMethod(name = "setrlimit", module = true, visibility = PRIVATE)
public static IRubyObject setrlimit(ThreadContext context, IRubyObject recv, IRubyObject resource, IRubyObject rlimCur, IRubyObject rlimMax) {
Ruby runtime = context.runtime;

RLimit rlim = runtime.getPosix().getrlimit(0);

if (rlimMax == context.nil)
rlimMax = rlimCur;

rlim.init(rlimitResourceValue(runtime, rlimCur), rlimitResourceValue(runtime, rlimMax));

if (runtime.getPosix().setrlimit(rlimitResourceType(runtime, resource), rlim) < 0) {
throw runtime.newErrnoFromInt(runtime.getPosix().errno(), "setrlimit");
}
return context.nil;
}

private static int rlimitResourceValue(Ruby runtime, IRubyObject rval) {
String name;
IRubyObject v;

switch (((CoreObjectType) rval).getNativeClassIndex()) {
case SYMBOL:
name = rval.toString();
break;

case STRING:
name = rval.toString();
break;

default:
v = TypeConverter.checkStringType(runtime, rval);
if (!v.isNil()) {
rval = v;
name = rval.convertToString().toString();
break;
}
/* fall through */

case FIXNUM:
case BIGNUM:
return rval.convertToInteger().getIntValue();
}

if (RLIM.RLIM_INFINITY.defined()) {
if (name.equals("INFINITY")) return RLIM.RLIM_INFINITY.intValue();
}
if (RLIM.RLIM_SAVED_MAX.defined()) {
if (name.equals("SAVED_MAX")) return RLIM.RLIM_SAVED_MAX.intValue();
}
if (RLIM.RLIM_SAVED_CUR.defined()) {
if (name.equals("SAVED_CUR")) return RLIM.RLIM_SAVED_CUR.intValue();
}

throw runtime.newArgumentError("invalid resource value: " + rval);
}

// MRI: rlimit_resource_type
private static int rlimitResourceType(Ruby runtime, IRubyObject rtype) {
String name;
IRubyObject v;
int r;

switch (((CoreObjectType) rtype).getNativeClassIndex()) {
case SYMBOL:
name = rtype.toString();
break;

case STRING:
name = rtype.toString();
break;

default:
v = TypeConverter.checkStringType(runtime, rtype);
if (!v.isNil()) {
rtype = v;
name = rtype.toString();
break;
}
/* fall through */

case FIXNUM:
case BIGNUM:
return rtype.convertToInteger().getIntValue();
}

r = rlimitTypeByHname(name);
if (r != -1)
return r;

throw runtime.newArgumentError("invalid resource name: " + rtype);
}

// MRI: rlimit_resource_name2int
private static int rlimitResourceName2int(String name, int casetype) {
RLIMIT resource;

OUTER: while (true) {
switch (Character.toUpperCase(name.charAt(0))) {
case 'A':
if (RLIMIT.RLIMIT_AS.defined()) {
if (name.equalsIgnoreCase("AS")) {
resource = RLIMIT.RLIMIT_AS;
break OUTER;
}
}
break;

case 'C':
if (RLIMIT.RLIMIT_CORE.defined()) {
if (name.equalsIgnoreCase("CORE")) {
resource = RLIMIT.RLIMIT_CORE;
break OUTER;
}
}
if (RLIMIT.RLIMIT_CPU.defined()) {
if (name.equalsIgnoreCase("CPU")) {
resource = RLIMIT.RLIMIT_CPU;
break OUTER;
}
}
break;

case 'D':
if (RLIMIT.RLIMIT_DATA.defined()) {
if (name.equalsIgnoreCase("DATA")) {
resource = RLIMIT.RLIMIT_DATA;
break OUTER;
}
}
break;

case 'F':
if (RLIMIT.RLIMIT_FSIZE.defined()) {
if (name.equalsIgnoreCase("FSIZE")) {
resource = RLIMIT.RLIMIT_FSIZE;
break OUTER;
}
}
break;

case 'M':
if (RLIMIT.RLIMIT_MEMLOCK.defined()) {
if (name.equalsIgnoreCase("MEMLOCK")) {
resource = RLIMIT.RLIMIT_MEMLOCK;
break OUTER;
}
}
if (RLIMIT.RLIMIT_MSGQUEUE.defined()) {
if (name.equalsIgnoreCase("MSGQUEUE")) {
resource = RLIMIT.RLIMIT_MSGQUEUE;
break OUTER;
}
}
break;

case 'N':
if (RLIMIT.RLIMIT_NOFILE.defined()) {
if (name.equalsIgnoreCase("NOFILE")) {
resource = RLIMIT.RLIMIT_NOFILE;
break OUTER;
}
}
if (RLIMIT.RLIMIT_NPROC.defined()) {
if (name.equalsIgnoreCase("NPROC")) {
resource = RLIMIT.RLIMIT_NPROC;
break OUTER;
}
}
if (RLIMIT.RLIMIT_NICE.defined()) {
if (name.equalsIgnoreCase("NICE")) {
resource = RLIMIT.RLIMIT_NICE;
break OUTER;
}
}
break;

case 'R':
if (RLIMIT.RLIMIT_RSS.defined()) {
if (name.equalsIgnoreCase("RSS")) {
resource = RLIMIT.RLIMIT_RSS;
break OUTER;
}
}
if (RLIMIT.RLIMIT_RTPRIO.defined()) {
if (name.equalsIgnoreCase("RTPRIO")) {
resource = RLIMIT.RLIMIT_RTPRIO;
break OUTER;
}
}
if (RLIMIT.RLIMIT_RTTIME.defined()) {
if (name.equalsIgnoreCase("RTTIME")) {
resource = RLIMIT.RLIMIT_RTTIME;
break OUTER;
}
}
break;

case 'S':
if (RLIMIT.RLIMIT_STACK.defined()) {
if (name.equalsIgnoreCase("STACK")) {
resource = RLIMIT.RLIMIT_STACK;
break OUTER;
}
}
// Not provided by jnr-constants
// if (RLIMIT.RLIMIT_SBSIZE.defined()) {
// if (name.equalsIgnoreCase("SBSIZE") { resource = RLIMIT.RLIMIT_SBSIZE; break OUTER; }
// }
if (RLIMIT.RLIMIT_SIGPENDING.defined()) {
if (name.equalsIgnoreCase("SIGPENDING")) {
resource = RLIMIT.RLIMIT_SIGPENDING;
break OUTER;
}
}
break;
}
return -1;
}

switch (casetype) {
case 0:
if (!name.equals(name.toUpperCase())) return -1;
break;

case 1:
if (!name.equals(name.toLowerCase())) return -1;
break;

default:
throw new RuntimeException("unexpected casetype");
}

return resource.intValue();
}

// MRI: rlimit_type_by_hname
private static int rlimitTypeByHname(String name) {
return rlimitResourceName2int(name, 0);
}

@Deprecated
@@ -962,9 +1208,9 @@ public static IRubyObject getrlimit(Ruby runtime, IRubyObject arg) {
return runtime.newFixnum(Long.MAX_VALUE);
}

RLimit rlimit = runtime.getPosix().getrlimit(arg.convertToInteger().getIntValue());
RLimit rlimit = runtime.getPosix().getrlimit(rlimitResourceType(runtime, arg));

return runtime.newFixnum(rlimit.rlimCur());
return runtime.newArray(runtime.newFixnum(rlimit.rlimCur()), runtime.newFixnum(rlimit.rlimMax()));
}

@Deprecated
@@ -1187,6 +1433,11 @@ public static IRubyObject clock_gettime(ThreadContext context, IRubyObject self,
return makeClockResult(runtime, getTimeForClock(_clock_id, runtime), _unit.toString());
}

@JRubyMethod(rest = true, meta = true)
public static IRubyObject exec(ThreadContext context, IRubyObject self, IRubyObject[] args) {
return RubyKernel.exec(context, self, args);
}

/**
* Get the time in nanoseconds corresponding to the requested clock.
*/
13 changes: 11 additions & 2 deletions core/src/main/java/org/jruby/RubyStruct.java
Original file line number Diff line number Diff line change
@@ -119,12 +119,21 @@ private void modify() {
}

@JRubyMethod
public RubyFixnum hash(ThreadContext context) {
public RubyFixnum hash(final ThreadContext context) {
final Ruby runtime = context.runtime;
int h = getMetaClass().getRealClass().hashCode();


for (int i = 0; i < values.length; i++) {
h = (h << 1) | (h < 0 ? 1 : 0);
h ^= RubyNumeric.num2long(invokedynamic(context, values[i], HASH));
IRubyObject hash = runtime.execRecursiveOuter(new Ruby.RecursiveFunction() {
@Override
public IRubyObject call(IRubyObject obj, boolean recur) {
if (recur) return RubyFixnum.zero(runtime);
return invokedynamic(context, obj, HASH);
}
}, values[i]);
h ^= RubyNumeric.num2long(hash);
}

return context.runtime.newFixnum(h);
2 changes: 2 additions & 0 deletions core/src/main/java/org/jruby/runtime/Helpers.java
Original file line number Diff line number Diff line change
@@ -274,6 +274,8 @@ public static Errno errnoFromException(Throwable t) {
return Errno.ECONNRESET;
} else if (errorMessage.equals("No space left on device")) {
return Errno.ENOSPC;
} else if (errorMessage.equals("Too many open files")) {
return Errno.EMFILE;
}
}
return null;
5 changes: 4 additions & 1 deletion lib/ruby/stdlib/date.rb
Original file line number Diff line number Diff line change
@@ -886,13 +886,16 @@ def self.rewrite_frags(elem) # :nodoc:
h, fr = fr.divmod(3600)
min, fr = fr.divmod(60)
s, fr = fr.divmod(1)
offset = elem[:offset]
unless offset.nil?
seconds += offset
end
elem[:jd] = UNIX_EPOCH_IN_CJD + d
elem[:hour] = h
elem[:min] = min
elem[:sec] = s
elem[:sec_fraction] = fr
elem.delete(:seconds)
elem.delete(:offset)
end
elem
end
5 changes: 5 additions & 0 deletions test/mri/excludes/TestPack.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
exclude :test_format_string_modified, "needs investigation"
exclude :test_integer_endian, "needs investigation"
exclude :test_integer_endian_explicit, "needs investigation"
exclude :test_invalid_warning, "needs investigation"
exclude :test_length_too_big, "needs investigation"
exclude :test_pack_P, "needs investigation"
exclude :test_pack_garbage, "needs investigation"
exclude :test_pack_p, "needs investigation"
exclude :test_pack_resize, "needs investigation"
exclude :test_pack_unpack_P2, "needs investigation"
exclude :test_pack_unpack_M, "needs investigation"
exclude :test_pack_unpack_bB, "needs investigation"
exclude :test_pack_unpack_hH, "needs investigation"
exclude :test_pack_unpack_jJ, "pointer packing, may not be relevant or useful in JRuby"
exclude :test_pack_unpack_m, "needs investigation"
exclude :test_pack_unpack_m0, "needs investigation"
exclude :test_pack_unpack_qQ, "needs investigation"
1 change: 1 addition & 0 deletions test/mri/excludes/TestProcess.rb
Original file line number Diff line number Diff line change
@@ -35,6 +35,7 @@
exclude :test_execopts_redirect_pipe, "hangs"
exclude :test_execopts_redirect_symbol, "Errno::ENOENT: No such file or directory - out"
exclude :test_execopts_redirect_to_out_and_err, "Errno::ENOENT: No such file or directory - foo"
exclude :test_execopts_rlimit, "posix_spawn does not support rlimit modification"
#exclude :test_execopts_uid, "doesn't really pass but test seems OK due throwing NotImplementedError"
exclude :test_execopts_umask, "unsupported"
exclude :test_execopts_unsetenv_others, "unsupported"
Loading