@ -19,6 +19,8 @@ package org.apache.dolphinscheduler.common.utils.process;
import com.sun.jna.Pointer ;
import com.sun.jna.Pointer ;
import com.sun.jna.platform.win32.* ;
import com.sun.jna.platform.win32.* ;
import com.sun.jna.ptr.IntByReference ;
import com.sun.jna.ptr.IntByReference ;
import java.lang.reflect.Field ;
import org.apache.dolphinscheduler.common.utils.OSUtils ;
import sun.security.action.GetPropertyAction ;
import sun.security.action.GetPropertyAction ;
import java.io.* ;
import java.io.* ;
@ -31,10 +33,25 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern ;
import java.util.regex.Pattern ;
import static com.sun.jna.platform.win32.WinBase.STILL_ACTIVE ;
import static com.sun.jna.platform.win32.WinBase.STILL_ACTIVE ;
import static java.util.Objects.requireNonNull ;
public class ProcessImplForWin32 extends Process {
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 ;
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 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
* Open a file for writing . If { @code append } is { @code true } then the file
* is opened for atomic append directly and a FileOutputStream constructed
* is opened for atomic append directly and a FileOutputStream constructed
@ -63,7 +96,7 @@ public class ProcessImplForWin32 extends Process {
sm . checkWrite ( path ) ;
sm . checkWrite ( path ) ;
long handle = openForAtomicAppend ( path ) ;
long handle = openForAtomicAppend ( path ) ;
final FileDescriptor fd = new FileDescriptor ( ) ;
final FileDescriptor fd = new FileDescriptor ( ) ;
fdAccess . setHandle ( fd , handle ) ;
setHandle ( fd , handle ) ;
return AccessController . doPrivileged (
return AccessController . doPrivileged (
new PrivilegedAction < FileOutputStream > ( ) {
new PrivilegedAction < FileOutputStream > ( ) {
public FileOutputStream run ( ) {
public FileOutputStream run ( ) {
@ -102,30 +135,30 @@ public class ProcessImplForWin32 extends Process {
if ( redirects [ 0 ] = = ProcessBuilderForWin32 . Redirect . PIPE )
if ( redirects [ 0 ] = = ProcessBuilderForWin32 . Redirect . PIPE )
stdHandles [ 0 ] = - 1L ;
stdHandles [ 0 ] = - 1L ;
else if ( redirects [ 0 ] = = ProcessBuilderForWin32 . Redirect . INHERIT )
else if ( redirects [ 0 ] = = ProcessBuilderForWin32 . Redirect . INHERIT )
stdHandles [ 0 ] = fdAccess . getHandle ( FileDescriptor . in ) ;
stdHandles [ 0 ] = getHandle ( FileDescriptor . in ) ;
else {
else {
f0 = new FileInputStream ( redirects [ 0 ] . file ( ) ) ;
f0 = new FileInputStream ( redirects [ 0 ] . file ( ) ) ;
stdHandles [ 0 ] = fdAccess . getHandle ( f0 . getFD ( ) ) ;
stdHandles [ 0 ] = getHandle ( f0 . getFD ( ) ) ;
}
}
if ( redirects [ 1 ] = = ProcessBuilderForWin32 . Redirect . PIPE )
if ( redirects [ 1 ] = = ProcessBuilderForWin32 . Redirect . PIPE )
stdHandles [ 1 ] = - 1L ;
stdHandles [ 1 ] = - 1L ;
else if ( redirects [ 1 ] = = ProcessBuilderForWin32 . Redirect . INHERIT )
else if ( redirects [ 1 ] = = ProcessBuilderForWin32 . Redirect . INHERIT )
stdHandles [ 1 ] = fdAccess . getHandle ( FileDescriptor . out ) ;
stdHandles [ 1 ] = getHandle ( FileDescriptor . out ) ;
else {
else {
f1 = newFileOutputStream ( redirects [ 1 ] . file ( ) ,
f1 = newFileOutputStream ( redirects [ 1 ] . file ( ) ,
redirects [ 1 ] . append ( ) ) ;
redirects [ 1 ] . append ( ) ) ;
stdHandles [ 1 ] = fdAccess . getHandle ( f1 . getFD ( ) ) ;
stdHandles [ 1 ] = getHandle ( f1 . getFD ( ) ) ;
}
}
if ( redirects [ 2 ] = = ProcessBuilderForWin32 . Redirect . PIPE )
if ( redirects [ 2 ] = = ProcessBuilderForWin32 . Redirect . PIPE )
stdHandles [ 2 ] = - 1L ;
stdHandles [ 2 ] = - 1L ;
else if ( redirects [ 2 ] = = ProcessBuilderForWin32 . Redirect . INHERIT )
else if ( redirects [ 2 ] = = ProcessBuilderForWin32 . Redirect . INHERIT )
stdHandles [ 2 ] = fdAccess . getHandle ( FileDescriptor . err ) ;
stdHandles [ 2 ] = getHandle ( FileDescriptor . err ) ;
else {
else {
f2 = newFileOutputStream ( redirects [ 2 ] . file ( ) ,
f2 = newFileOutputStream ( redirects [ 2 ] . file ( ) ,
redirects [ 2 ] . append ( ) ) ;
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 ;
stdin_stream = ProcessBuilderForWin32 . NullOutputStream . INSTANCE ;
else {
else {
FileDescriptor stdin_fd = new FileDescriptor ( ) ;
FileDescriptor stdin_fd = new FileDescriptor ( ) ;
fdAccess . setHandle ( stdin_fd , stdHandles [ 0 ] ) ;
setHandle ( stdin_fd , stdHandles [ 0 ] ) ;
stdin_stream = new BufferedOutputStream (
stdin_stream = new BufferedOutputStream (
new FileOutputStream ( stdin_fd ) ) ;
new FileOutputStream ( stdin_fd ) ) ;
}
}
@ -451,7 +484,7 @@ public class ProcessImplForWin32 extends Process {
stdout_stream = ProcessBuilderForWin32 . NullInputStream . INSTANCE ;
stdout_stream = ProcessBuilderForWin32 . NullInputStream . INSTANCE ;
else {
else {
FileDescriptor stdout_fd = new FileDescriptor ( ) ;
FileDescriptor stdout_fd = new FileDescriptor ( ) ;
fdAccess . setHandle ( stdout_fd , stdHandles [ 1 ] ) ;
setHandle ( stdout_fd , stdHandles [ 1 ] ) ;
stdout_stream = new BufferedInputStream (
stdout_stream = new BufferedInputStream (
new FileInputStream ( stdout_fd ) ) ;
new FileInputStream ( stdout_fd ) ) ;
}
}
@ -460,7 +493,7 @@ public class ProcessImplForWin32 extends Process {
stderr_stream = ProcessBuilderForWin32 . NullInputStream . INSTANCE ;
stderr_stream = ProcessBuilderForWin32 . NullInputStream . INSTANCE ;
else {
else {
FileDescriptor stderr_fd = new FileDescriptor ( ) ;
FileDescriptor stderr_fd = new FileDescriptor ( ) ;
fdAccess . setHandle ( stderr_fd , stdHandles [ 2 ] ) ;
setHandle ( stderr_fd , stdHandles [ 2 ] ) ;
stderr_stream = new FileInputStream ( stderr_fd ) ;
stderr_stream = new FileInputStream ( stderr_fd ) ;
}
}