diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/OSUtils.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/OSUtils.java index acfca77c8c..b011c0bc4e 100644 --- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/OSUtils.java +++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/OSUtils.java @@ -400,8 +400,7 @@ public class OSUtils { * @return true if mac */ public static boolean isMacOS() { - String os = System.getProperty("os.name"); - return os.startsWith("Mac"); + return getOSName().startsWith("Mac"); } @@ -409,9 +408,16 @@ public class OSUtils { * whether is windows * @return true if windows */ - public static boolean isWindows() { - String os = System.getProperty("os.name"); - return os.startsWith("Windows"); + public static boolean isWindows() { ; + return getOSName().startsWith("Windows"); + } + + /** + * get current OS name + * @return current OS name + */ + public static String getOSName() { + return System.getProperty("os.name"); } /** diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/process/ProcessImplForWin32.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/process/ProcessImplForWin32.java index 4583be8aff..9f2716a096 100644 --- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/process/ProcessImplForWin32.java +++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/process/ProcessImplForWin32.java @@ -19,6 +19,8 @@ package org.apache.dolphinscheduler.common.utils.process; import com.sun.jna.Pointer; import com.sun.jna.platform.win32.*; import com.sun.jna.ptr.IntByReference; +import java.lang.reflect.Field; +import org.apache.dolphinscheduler.common.utils.OSUtils; import sun.security.action.GetPropertyAction; import java.io.*; @@ -31,10 +33,25 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import static com.sun.jna.platform.win32.WinBase.STILL_ACTIVE; +import static java.util.Objects.requireNonNull; public class ProcessImplForWin32 extends Process { - private static final sun.misc.JavaIOFileDescriptorAccess fdAccess - = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess(); + + private static final Field FD_HANDLE; + + static { + if (!OSUtils.isWindows()) { + throw new RuntimeException("ProcessImplForWin32 can be only initialized in " + + "Windows environment, but current OS is " + OSUtils.getOSName()); + } + + try { + FD_HANDLE = requireNonNull(FileDescriptor.class.getDeclaredField("handle")); + FD_HANDLE.setAccessible(true); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + } private static final int PIPE_SIZE = 4096 + 24; @@ -46,6 +63,22 @@ public class ProcessImplForWin32 extends Process { private static final WinNT.HANDLE JAVA_INVALID_HANDLE_VALUE = new WinNT.HANDLE(Pointer.createConstant(-1)); + private static void setHandle(FileDescriptor obj, long handle) { + try { + FD_HANDLE.set(obj, handle); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private static long getHandle(FileDescriptor obj) { + try { + return (Long) FD_HANDLE.get(obj); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + /** * Open a file for writing. If {@code append} is {@code true} then the file * is opened for atomic append directly and a FileOutputStream constructed @@ -63,7 +96,7 @@ public class ProcessImplForWin32 extends Process { sm.checkWrite(path); long handle = openForAtomicAppend(path); final FileDescriptor fd = new FileDescriptor(); - fdAccess.setHandle(fd, handle); + setHandle(fd, handle); return AccessController.doPrivileged( new PrivilegedAction() { public FileOutputStream run() { @@ -102,30 +135,30 @@ public class ProcessImplForWin32 extends Process { if (redirects[0] == ProcessBuilderForWin32.Redirect.PIPE) stdHandles[0] = -1L; else if (redirects[0] == ProcessBuilderForWin32.Redirect.INHERIT) - stdHandles[0] = fdAccess.getHandle(FileDescriptor.in); + stdHandles[0] = getHandle(FileDescriptor.in); else { f0 = new FileInputStream(redirects[0].file()); - stdHandles[0] = fdAccess.getHandle(f0.getFD()); + stdHandles[0] = getHandle(f0.getFD()); } if (redirects[1] == ProcessBuilderForWin32.Redirect.PIPE) stdHandles[1] = -1L; else if (redirects[1] == ProcessBuilderForWin32.Redirect.INHERIT) - stdHandles[1] = fdAccess.getHandle(FileDescriptor.out); + stdHandles[1] = getHandle(FileDescriptor.out); else { f1 = newFileOutputStream(redirects[1].file(), redirects[1].append()); - stdHandles[1] = fdAccess.getHandle(f1.getFD()); + stdHandles[1] = getHandle(f1.getFD()); } if (redirects[2] == ProcessBuilderForWin32.Redirect.PIPE) stdHandles[2] = -1L; else if (redirects[2] == ProcessBuilderForWin32.Redirect.INHERIT) - stdHandles[2] = fdAccess.getHandle(FileDescriptor.err); + stdHandles[2] = getHandle(FileDescriptor.err); else { f2 = newFileOutputStream(redirects[2].file(), redirects[2].append()); - stdHandles[2] = fdAccess.getHandle(f2.getFD()); + stdHandles[2] = getHandle(f2.getFD()); } } @@ -442,7 +475,7 @@ public class ProcessImplForWin32 extends Process { stdin_stream = ProcessBuilderForWin32.NullOutputStream.INSTANCE; else { FileDescriptor stdin_fd = new FileDescriptor(); - fdAccess.setHandle(stdin_fd, stdHandles[0]); + setHandle(stdin_fd, stdHandles[0]); stdin_stream = new BufferedOutputStream( new FileOutputStream(stdin_fd)); } @@ -451,7 +484,7 @@ public class ProcessImplForWin32 extends Process { stdout_stream = ProcessBuilderForWin32.NullInputStream.INSTANCE; else { FileDescriptor stdout_fd = new FileDescriptor(); - fdAccess.setHandle(stdout_fd, stdHandles[1]); + setHandle(stdout_fd, stdHandles[1]); stdout_stream = new BufferedInputStream( new FileInputStream(stdout_fd)); } @@ -460,7 +493,7 @@ public class ProcessImplForWin32 extends Process { stderr_stream = ProcessBuilderForWin32.NullInputStream.INSTANCE; else { FileDescriptor stderr_fd = new FileDescriptor(); - fdAccess.setHandle(stderr_fd, stdHandles[2]); + setHandle(stderr_fd, stdHandles[2]); stderr_stream = new FileInputStream(stderr_fd); } diff --git a/dolphinscheduler-server/src/test/java/org/apache/dolphinscheduler/server/worker/task/shell/ShellTaskTest.java b/dolphinscheduler-server/src/test/java/org/apache/dolphinscheduler/server/worker/task/shell/ShellTaskTest.java index 5536665e26..ebe90147d1 100644 --- a/dolphinscheduler-server/src/test/java/org/apache/dolphinscheduler/server/worker/task/shell/ShellTaskTest.java +++ b/dolphinscheduler-server/src/test/java/org/apache/dolphinscheduler/server/worker/task/shell/ShellTaskTest.java @@ -27,6 +27,7 @@ import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; import org.apache.dolphinscheduler.service.process.ProcessService; import org.junit.After; import org.junit.Assert; +import org.junit.Assume; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -172,7 +173,7 @@ public class ShellTaskTest { @Test public void testHandleForWindows() throws Exception { try { - PowerMockito.when(OSUtils.isWindows()).thenReturn(true); + Assume.assumeTrue(OSUtils.isWindows()); shellTask.handle(); Assert.assertTrue(true); } catch (Error | Exception e) {