Hide
added a comment - - edited
Looks like this is caused by commit 10e567b3 which fixed an issue where SystemCallError.new is supposed to return instance of Errno subclasses under certain circumstances. However it appears that this logic, placed into SystemCallError#initialize, should have been in SystemCallError.new.
Here's a patch that seems to make the case pass, but I have not run tests and have not checked whether it changes other behaviors in the process:
Show
added a comment - - edited Looks like this is caused by commit 10e567b3 which fixed an issue where SystemCallError.new is supposed to return instance of Errno subclasses under certain circumstances. However it appears that this logic, placed into SystemCallError#initialize, should have been in SystemCallError.new.
Here's a patch that seems to make the case pass, but I have not run tests and have not checked whether it changes other behaviors in the process:
diff --git a/src/org/jruby/RubySystemCallError.java b/src/org/jruby/RubySystemCallError.java
index 52868c1..fbaa9a5 100644
--- a/src/org/jruby/RubySystemCallError.java
+++ b/src/org/jruby/RubySystemCallError.java
@@ -20,6 +20,7 @@ import org.jruby.runtime.marshal.MarshalStream;
import org.jruby.runtime.marshal.UnmarshalStream;
import com.kenai.constantine.platform.Errno;
+import org.jruby.runtime.ThreadContext;
@JRubyClass(name="SystemCallError", parent="StandardError")
public class RubySystemCallError extends RubyException {
@@ -174,79 +175,84 @@ public class RubySystemCallError extends RubyException {
runtime.callbackFactory(RubyClass.class);
exceptionClass.defineAnnotatedMethods(RubySystemCallError.class);
+ exceptionClass.getSingletonClass().defineAnnotatedMethods(SystemCallErrorNew.class);
return exceptionClass;
}
-
- @JRubyMethod(optional = 2, required=0, frame = true, visibility = Visibility.PRIVATE)
- public IRubyObject initialize(IRubyObject[] args, Block block) {
- Ruby runtime = getRuntime();
- RubyClass sCallErorrClass = runtime.getSystemCallError();
- RubyClass klass = getMetaClass().getRealClass();
- IRubyObject msg = runtime.getNil();
- IRubyObject err = runtime.getNil();
+ public static class SystemCallErrorNew {
+ @JRubyMethod(name = "new", optional = 2, required=0, frame = true, meta = true)
+ public static IRubyObject newInstance(ThreadContext context, IRubyObject self, IRubyObject[] args, Block block) {
+ Ruby runtime = context.getRuntime();
+ RubyClass sCallErorrClass = runtime.getSystemCallError();
+ RubyClass klass = (RubyClass)self;
- boolean isErrnoClass = !klass.equals(sCallErorrClass);
+ IRubyObject msg = runtime.getNil();
+ IRubyObject err = runtime.getNil();
- if (!isErrnoClass) {
- // one optional, one required args
- Arity.checkArgumentCount(runtime, args, 1, 2);
- msg = args[0];
- if (args.length == 2) {
- err = args[1];
- }
- if (args.length == 1 && (msg instanceof RubyFixnum)) {
- err = msg;
- msg = runtime.getNil();
- }
- } else {
- // one optional and no required args
- Arity.checkArgumentCount(runtime, args, 0, 1);
- if (args.length == 1) {
+ boolean isErrnoClass = !klass.equals(sCallErorrClass);
+
+ if (!isErrnoClass) {
+ // one optional, one required args
+ Arity.checkArgumentCount(runtime, args, 1, 2);
msg = args[0];
+ if (args.length == 2) {
+ err = args[1];
+ }
+ if (args.length == 1 && (msg instanceof RubyFixnum)) {
+ err = msg;
+ msg = runtime.getNil();
+ }
+ } else {
+ // one optional and no required args
+ Arity.checkArgumentCount(runtime, args, 0, 1);
+ if (args.length == 1) {
+ msg = args[0];
+ }
+ // try to get errno value out of the class
+ err = klass.fastGetConstant("Errno");
}
- // try to get errno value out of the class
- err = klass.fastGetConstant("Errno");
- }
- String val = null;
+ String val = null;
+
+ RubySystemCallError sysCallError = new RubySystemCallError(runtime, klass);
- if (!err.isNil()) {
- errno = err.convertToInteger();
- int errnoVal = RubyNumeric.num2int(errno);
- if (Errno.valueOf(errnoVal) != Errno.__UNKNOWN_CONSTANT__) {
- // we got a valid errno value
- isErrnoClass = true;
- setMetaClass(runtime.getErrno(errnoVal));
- klass = getMetaClass().getRealClass();
+ if (!err.isNil()) {
+ sysCallError.errno = err.convertToInteger();
+ int errnoVal = RubyNumeric.num2int(sysCallError.errno);
+ if (Errno.valueOf(errnoVal) != Errno.__UNKNOWN_CONSTANT__) {
+ // we got a valid errno value
+ isErrnoClass = true;
+ sysCallError.setMetaClass(runtime.getErrno(errnoVal));
+ klass = sysCallError.getMetaClass().getRealClass();
- // FIXME: Errno descriptions from Constantine
- // on Windows are not useful at the moment.
- if (!Platform.IS_WINDOWS) {
- val = Errno.valueOf(errnoVal).description();
+ // FIXME: Errno descriptions from Constantine
+ // on Windows are not useful at the moment.
+ if (!Platform.IS_WINDOWS) {
+ val = Errno.valueOf(errnoVal).description();
+ }
}
}
- }
- if (val == null) {
- val = defaultMessages.get(klass.getName());
if (val == null) {
- val = "Unknown error";
+ val = defaultMessages.get(klass.getName());
+ if (val == null) {
+ val = "Unknown error";
+ }
}
- }
- // MRI behavior: we don't print errno for actual Errno errors
- if (!errno.isNil() && !isErrnoClass) {
- val += " " + errno.toString();
- }
+ // MRI behavior: we don't print errno for actual Errno errors
+ if (!sysCallError.errno.isNil() && !isErrnoClass) {
+ val += " " + sysCallError.errno.toString();
+ }
- if (!msg.isNil()) {
- val += " - " + msg.convertToString();
- }
+ if (!msg.isNil()) {
+ val += " - " + msg.convertToString();
+ }
- message = runtime.newString(val);
- return this;
+ sysCallError.message = runtime.newString(val);
+ return sysCallError;
+ }
}
@JRubyMethod
Appears to be fixed.