Skip to content

Commit c5313a0

Browse files
committedDec 12, 2017
Centralize IOException => Errno translation logic.
1 parent 3493a91 commit c5313a0

File tree

3 files changed

+26
-45
lines changed

3 files changed

+26
-45
lines changed
 

‎core/src/main/java/org/jruby/Ruby.java

+1-40
Original file line numberDiff line numberDiff line change
@@ -4045,46 +4045,7 @@ public RaiseException newStandardError(String message) {
40454045
* TODO: Should we include this into Errno code somewhere do we can use this from other places as well?
40464046
*/
40474047
public RaiseException newIOErrorFromException(final IOException ex) {
4048-
final String errorMessage = ex.getMessage();
4049-
if ( errorMessage != null ) {
4050-
// All errors to sysread should be SystemCallErrors, but on a closed stream
4051-
// Ruby returns an IOError. Java throws same exception for all errors so
4052-
// we resort to this hack...
4053-
switch ( errorMessage ) {
4054-
case "Bad file descriptor" :
4055-
if ( ex instanceof ClosedChannelException ) throw newErrnoEBADFError();
4056-
break;
4057-
case "File not open" :
4058-
return newIOError(errorMessage);
4059-
case "An established connection was aborted by the software in your host machine" :
4060-
return newErrnoECONNABORTEDError();
4061-
case "Broken pipe" :
4062-
return newErrnoEPIPEError();
4063-
case "Connection reset by peer" :
4064-
case "An existing connection was forcibly closed by the remote host" :
4065-
return newErrnoECONNRESETError();
4066-
case "Too many levels of symbolic links" :
4067-
return newErrnoELOOPError();
4068-
case "Too many open files" :
4069-
return newErrnoEMFILEError();
4070-
case "Too many open files in system" :
4071-
return newErrnoENFILEError();
4072-
case "Network is unreachable" :
4073-
return newErrnoENETUNREACHError();
4074-
case "Address already in use" :
4075-
return newErrnoEADDRINUSEError();
4076-
default :
4077-
if ( Platform.IS_WINDOWS ) {
4078-
if ( errorMessage.contains("connection was aborted") ) {
4079-
return newErrnoECONNRESETError();
4080-
}
4081-
}
4082-
}
4083-
return newRaiseException(getIOError(), errorMessage);
4084-
} else if (ex instanceof PortUnreachableException) {
4085-
throw newErrnoECONNREFUSEDError();
4086-
}
4087-
return newRaiseException(getIOError(), "IO Error");
4048+
return Helpers.newIOErrorFromException(this, ex);
40884049
}
40894050

40904051
public RaiseException newTypeError(IRubyObject receivedObject, RubyClass expectedType) {

‎core/src/main/java/org/jruby/runtime/Helpers.java

+24-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package org.jruby.runtime;
22

3-
import java.lang.reflect.AccessibleObject;
4-
import java.lang.reflect.Array;
5-
import java.lang.reflect.Member;
3+
import org.jruby.platform.Platform;
4+
5+
import java.net.PortUnreachableException;
66
import java.nio.channels.ClosedChannelException;
7+
import java.io.IOException;
8+
import java.lang.reflect.Array;
79
import java.nio.charset.Charset;
810
import java.util.ArrayList;
911
import java.util.Arrays;
@@ -268,7 +270,8 @@ public static Errno errnoFromException(Throwable t) {
268270
// All errors to sysread should be SystemCallErrors, but on a closed stream
269271
// Ruby returns an IOError. Java throws same exception for all errors so
270272
// we resort to this hack...
271-
switch ( errorMessage ) {
273+
274+
switch (errorMessage) {
272275
case "Bad file descriptor":
273276
return Errno.EBADF;
274277
case "File not open":
@@ -299,10 +302,27 @@ public static Errno errnoFromException(Throwable t) {
299302
case "Is a directory":
300303
return Errno.EISDIR;
301304
}
305+
} else if (t instanceof PortUnreachableException) {
306+
return Errno.ECONNREFUSED;
302307
}
303308
return null;
304309
}
305310

311+
/**
312+
* Java does not give us enough information for specific error conditions
313+
* so we are reduced to divining them through string matches...
314+
*
315+
* TODO: Should ECONNABORTED get thrown earlier in the descriptor itself or is it ok to handle this late?
316+
* TODO: Should we include this into Errno code somewhere do we can use this from other places as well?
317+
*/
318+
public static RaiseException newIOErrorFromException(Ruby runtime, IOException ex) {
319+
Errno errno = errnoFromException(ex);
320+
321+
if (errno == null) throw runtime.newIOError(ex.getLocalizedMessage());
322+
323+
throw runtime.newErrnoFromErrno(errno, ex.getLocalizedMessage());
324+
}
325+
306326
public static RubyModule getNthScopeModule(StaticScope scope, int depth) {
307327
int n = depth;
308328
while (n > 0) {

‎core/src/main/java/org/jruby/util/io/PosixShim.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ public Channel open(String cwd, String path, ModeFlags flags, int perm) {
436436
} catch (ResourceException.TooManySymlinks e) {
437437
errno = Errno.ELOOP;
438438
} catch (IOException e) {
439-
throw new RuntimeException("Unhandled IOException: " + e.getLocalizedMessage(), e);
439+
errno = Helpers.errnoFromException(e);
440440
}
441441
return null;
442442
}

0 commit comments

Comments
 (0)
Please sign in to comment.