diff --git a/core/src/main/java/org/jruby/util/ShellLauncher.java b/core/src/main/java/org/jruby/util/ShellLauncher.java index 638ee070ab1..d686a8a496e 100644 --- a/core/src/main/java/org/jruby/util/ShellLauncher.java +++ b/core/src/main/java/org/jruby/util/ShellLauncher.java @@ -42,6 +42,7 @@ import java.io.PipedOutputStream; import java.io.PrintStream; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.util.ArrayList; @@ -659,6 +660,7 @@ public static long getPidFromProcess(Process process) { private static final Field UNIXProcess_pid; private static final Class ProcessImpl; private static final Field ProcessImpl_handle; + private static final Method ProcessImpl_pid; private interface PidGetter { long getPid(Process process); } private static final PidGetter PID_GETTER; @@ -681,7 +683,7 @@ private interface PidGetter { long getPid(Process process); } if (up != null) { try { pid = up.getDeclaredField("pid"); - Java.trySetAccessible(pid); + if (!Java.trySetAccessible(pid)) pid = null; } catch (NoSuchFieldException | SecurityException e) { // ignore and try windows version } @@ -694,69 +696,43 @@ private interface PidGetter { long getPid(Process process); } try { pi = Class.forName("java.lang.ProcessImpl"); handle = pi.getDeclaredField("handle"); - Java.trySetAccessible(handle); + if (!Java.trySetAccessible(handle)) { + handle = null; + } } catch (Exception e) { // ignore and use hashcode } + + Method pi_pid = null; + if (pi != null) { + try { + pi_pid = pi.getMethod("pid"); + if (!Java.trySetAccessible(pi_pid)) { + pi_pid = null; + if (handle == null) pi = null; + } + } catch (Exception e) { + // ignore and use hashcode + } + } ProcessImpl = pi; ProcessImpl_handle = handle; + ProcessImpl_pid = pi_pid; if (UNIXProcess_pid != null) { if (ProcessImpl_handle != null) { // try both - pidGetter = new PidGetter() { - public long getPid(Process process) { - try { - if (UNIXProcess.isInstance(process)) { - return (Integer)UNIXProcess_pid.get(process); - } else if (ProcessImpl.isInstance(process)) { - Long hproc = (Long) ProcessImpl_handle.get(process); - return WindowsFFI.getKernel32().GetProcessId(hproc); - } - } catch (Exception e) { - // ignore and use hashcode - } - return process.hashCode(); - } - }; + pidGetter = ShellLauncher::getPidBoth; } else { // just unix - pidGetter = new PidGetter() { - public long getPid(Process process) { - try { - if (UNIXProcess.isInstance(process)) { - return (Integer)UNIXProcess_pid.get(process); - } - } catch (Exception e) { - // ignore and use hashcode - } - return process.hashCode(); - } - }; + pidGetter = ShellLauncher::getPidUnix; } - } else if (ProcessImpl_handle != null) { + } else if (ProcessImpl_handle != null || ProcessImpl_pid != null) { // just windows - pidGetter = new PidGetter() { - public long getPid(Process process) { - try { - if (ProcessImpl.isInstance(process)) { - Long hproc = (Long) ProcessImpl_handle.get(process); - return WindowsFFI.getKernel32().GetProcessId(hproc); - } - - } catch (Exception e) { - // ignore and use hashcode - } - return process.hashCode(); - } - }; + pidGetter = ShellLauncher::getPidWindows; } else { // neither - default PidGetter - pidGetter = new PidGetter() { - public long getPid(Process process) { - return process.hashCode(); - } - }; + pidGetter = Object::hashCode; } PID_GETTER = pidGetter; } @@ -765,6 +741,57 @@ public static long reflectPidFromProcess(Process process) { return PID_GETTER.getPid(process); } + private static long getPidBoth(Process process) { + try { + if (UNIXProcess.isInstance(process)) { + return getPidUnix(process); + } else if (ProcessImpl.isInstance(process)) { + return getPidWindows(process); + } + } catch (Exception e) { + // fall back on hashcode + } + + return process.hashCode(); + } + + private static long getPidWindows(Process process) { + long pid = -1; + if (ProcessImpl_handle != null) { + try { + if (ProcessImpl.isInstance(process)) { + Long hproc = (Long) ProcessImpl_handle.get(process); + return WindowsFFI.getKernel32().GetProcessId(hproc); + } + } catch (Exception e) { + // fall back on pid logic + } + } + + if (pid == -1 && ProcessImpl_pid != null) { + // JDK > 8 has a new way to look it up and also can't use "handle" field anymore + try { + return (long) ProcessImpl_pid.invoke(process); + } catch (Exception e2) { + // fall back on hashcode + } + } + + return process.hashCode(); + } + + private static long getPidUnix(Process process) { + try { + if (UNIXProcess.isInstance(process)) { + return (Integer) UNIXProcess_pid.get(process); + } + } catch (Exception e) { + // fall back on hashcode + } + + return process.hashCode(); + } + public static Process run(Ruby runtime, IRubyObject string) throws IOException { return run(runtime, new IRubyObject[] {string}, false); }