Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
095ce48d
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
095ce48d
编写于
3月 10, 2008
作者:
M
martin
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
4960438: (process) Need IO redirection API for subprocesses
Reviewed-by: alanb, iris
上级
6d73e05f
变更
12
展开全部
显示空白变更内容
内联
并排
Showing
12 changed file
with
1680 addition
and
476 deletion
+1680
-476
src/share/classes/java/lang/Process.java
src/share/classes/java/lang/Process.java
+50
-21
src/share/classes/java/lang/ProcessBuilder.java
src/share/classes/java/lang/ProcessBuilder.java
+635
-91
src/share/classes/sun/misc/JavaIOFileDescriptorAccess.java
src/share/classes/sun/misc/JavaIOFileDescriptorAccess.java
+4
-0
src/solaris/classes/java/io/FileDescriptor.java
src/solaris/classes/java/io/FileDescriptor.java
+9
-1
src/solaris/classes/java/lang/ProcessImpl.java
src/solaris/classes/java/lang/ProcessImpl.java
+58
-1
src/solaris/classes/java/lang/UNIXProcess.java.linux
src/solaris/classes/java/lang/UNIXProcess.java.linux
+105
-79
src/solaris/classes/java/lang/UNIXProcess.java.solaris
src/solaris/classes/java/lang/UNIXProcess.java.solaris
+209
-183
src/solaris/native/java/lang/UNIXProcess_md.c
src/solaris/native/java/lang/UNIXProcess_md.c
+30
-21
src/windows/classes/java/io/FileDescriptor.java
src/windows/classes/java/io/FileDescriptor.java
+19
-14
src/windows/classes/java/lang/ProcessImpl.java
src/windows/classes/java/lang/ProcessImpl.java
+121
-29
src/windows/native/java/lang/ProcessImpl_md.c
src/windows/native/java/lang/ProcessImpl_md.c
+64
-33
test/java/lang/ProcessBuilder/Basic.java
test/java/lang/ProcessBuilder/Basic.java
+376
-3
未找到文件。
src/share/classes/java/lang/Process.java
浏览文件 @
095ce48d
...
@@ -41,18 +41,24 @@ import java.io.*;
...
@@ -41,18 +41,24 @@ import java.io.*;
* <p>The methods that create processes may not work well for special
* <p>The methods that create processes may not work well for special
* processes on certain native platforms, such as native windowing
* processes on certain native platforms, such as native windowing
* processes, daemon processes, Win16/DOS processes on Microsoft
* processes, daemon processes, Win16/DOS processes on Microsoft
* Windows, or shell scripts. The created subprocess does not have
* Windows, or shell scripts.
* its own terminal or console. All its standard I/O (i.e. stdin,
*
* stdout, stderr) operations will be redirected to the parent process
* <p>By default, the created subprocess does not have its own terminal
* through three streams
* or console. All its standard I/O (i.e. stdin, stdout, stderr)
* ({@link #getOutputStream()},
* operations will be redirected to the parent process, where they can
* {@link #getInputStream()},
* be accessed via the streams obtained using the methods
* {@link #getErrorStream()}).
* {@link #getOutputStream()},
* {@link #getInputStream()}, and
* {@link #getErrorStream()}.
* The parent process uses these streams to feed input to and get output
* The parent process uses these streams to feed input to and get output
* from the subprocess. Because some native platforms only provide
* from the subprocess. Because some native platforms only provide
* limited buffer size for standard input and output streams, failure
* limited buffer size for standard input and output streams, failure
* to promptly write the input stream or read the output stream of
* to promptly write the input stream or read the output stream of
* the subprocess may cause the subprocess to block, and even deadlock.
* the subprocess may cause the subprocess to block, or even deadlock.
*
* <p>Where desired, <a href="ProcessBuilder.html#redirect-input">
* subprocess I/O can also be redirected</a>
* using methods of the {@link ProcessBuilder} class.
*
*
* <p>The subprocess is not killed when there are no more references to
* <p>The subprocess is not killed when there are no more references to
* the {@code Process} object, but rather the subprocess
* the {@code Process} object, but rather the subprocess
...
@@ -62,16 +68,22 @@ import java.io.*;
...
@@ -62,16 +68,22 @@ import java.io.*;
* Process} object execute asynchronously or concurrently with respect
* Process} object execute asynchronously or concurrently with respect
* to the Java process that owns the {@code Process} object.
* to the Java process that owns the {@code Process} object.
*
*
* @author unascribed
* <p>As of 1.5, {@link ProcessBuilder#start()} is the preferred way
* @see ProcessBuilder
* to create a {@code Process}.
*
* @since JDK1.0
* @since JDK1.0
*/
*/
public
abstract
class
Process
{
public
abstract
class
Process
{
/**
/**
* Returns the output stream connected to the normal input of the
* Returns the output stream connected to the normal input of the
* subprocess. Output to the stream is piped into the standard
* subprocess. Output to the stream is piped into the standard
* input stream of the process represented by this {@code Process}
* input of the process represented by this {@code Process} object.
* object.
*
* <p>If the standard input of the subprocess has been redirected using
* {@link ProcessBuilder#redirectInput(Redirect)
* ProcessBuilder.redirectInput}
* then this method will return a
* <a href="ProcessBuilder.html#redirect-input">null output stream</a>.
*
*
* <p>Implementation note: It is a good idea for the returned
* <p>Implementation note: It is a good idea for the returned
* output stream to be buffered.
* output stream to be buffered.
...
@@ -84,30 +96,47 @@ public abstract class Process {
...
@@ -84,30 +96,47 @@ public abstract class Process {
/**
/**
* Returns the input stream connected to the normal output of the
* Returns the input stream connected to the normal output of the
* subprocess. The stream obtains data piped from the standard
* subprocess. The stream obtains data piped from the standard
* output stream of the process represented by this {@code
* output of the process represented by this {@code Process} object.
* Process} object.
*
* <p>If the standard output of the subprocess has been redirected using
* {@link ProcessBuilder#redirectOutput(Redirect)
* ProcessBuilder.redirectOutput}
* then this method will return a
* <a href="ProcessBuilder.html#redirect-output">null input stream</a>.
*
* <p>Otherwise, if the standard error of the subprocess has been
* redirected using
* {@link ProcessBuilder#redirectErrorStream(boolean)
* ProcessBuilder.redirectErrorStream}
* then the input stream returned by this method will receive the
* merged standard output and the standard error of the subprocess.
*
*
* <p>Implementation note: It is a good idea for the returned
* <p>Implementation note: It is a good idea for the returned
* input stream to be buffered.
* input stream to be buffered.
*
*
* @return the input stream connected to the normal output of the
* @return the input stream connected to the normal output of the
* subprocess
* subprocess
* @see ProcessBuilder#redirectErrorStream()
*/
*/
abstract
public
InputStream
getInputStream
();
abstract
public
InputStream
getInputStream
();
/**
/**
* Returns the input stream connected to the error output stream of
* Returns the input stream connected to the error output of the
* the subprocess. The stream obtains data piped from the error
* subprocess. The stream obtains data piped from the error output
* output stream of the process represented by this {@code Process}
* of the process represented by this {@code Process} object.
* object.
*
* <p>If the standard error of the subprocess has been redirected using
* {@link ProcessBuilder#redirectError(Redirect)
* ProcessBuilder.redirectError} or
* {@link ProcessBuilder#redirectErrorStream(boolean)
* ProcessBuilder.redirectErrorStream}
* then this method will return a
* <a href="ProcessBuilder.html#redirect-output">null input stream</a>.
*
*
* <p>Implementation note: It is a good idea for the returned
* <p>Implementation note: It is a good idea for the returned
* input stream to be buffered.
* input stream to be buffered.
*
*
* @return the input stream connected to the error output
stream
of
* @return the input stream connected to the error output of
* the subprocess
* the subprocess
* @see ProcessBuilder#redirectErrorStream()
*/
*/
abstract
public
InputStream
getErrorStream
();
abstract
public
InputStream
getErrorStream
();
...
...
src/share/classes/java/lang/ProcessBuilder.java
浏览文件 @
095ce48d
此差异已折叠。
点击以展开。
src/share/classes/sun/misc/JavaIOFileDescriptorAccess.java
浏览文件 @
095ce48d
...
@@ -33,4 +33,8 @@ import java.io.FileDescriptor;
...
@@ -33,4 +33,8 @@ import java.io.FileDescriptor;
public
interface
JavaIOFileDescriptorAccess
{
public
interface
JavaIOFileDescriptorAccess
{
public
void
set
(
FileDescriptor
obj
,
int
fd
);
public
void
set
(
FileDescriptor
obj
,
int
fd
);
public
int
get
(
FileDescriptor
fd
);
public
int
get
(
FileDescriptor
fd
);
// Only valid on Windows
public
void
setHandle
(
FileDescriptor
obj
,
long
handle
);
public
long
getHandle
(
FileDescriptor
obj
);
}
}
src/solaris/classes/java/io/FileDescriptor.java
浏览文件 @
095ce48d
...
@@ -152,11 +152,19 @@ public final class FileDescriptor {
...
@@ -152,11 +152,19 @@ public final class FileDescriptor {
public
int
get
(
FileDescriptor
obj
)
{
public
int
get
(
FileDescriptor
obj
)
{
return
obj
.
fd
;
return
obj
.
fd
;
}
}
public
void
setHandle
(
FileDescriptor
obj
,
long
handle
)
{
throw
new
UnsupportedOperationException
();
}
public
long
getHandle
(
FileDescriptor
obj
)
{
throw
new
UnsupportedOperationException
();
}
}
}
);
);
}
}
// pac
akge private methods used by FIS,
FOS and RAF
// pac
kage private methods used by FIS,
FOS and RAF
int
incrementAndGetUseCount
()
{
int
incrementAndGetUseCount
()
{
return
useCount
.
incrementAndGet
();
return
useCount
.
incrementAndGet
();
...
...
src/solaris/classes/java/lang/ProcessImpl.java
浏览文件 @
095ce48d
...
@@ -26,7 +26,10 @@
...
@@ -26,7 +26,10 @@
package
java.lang
;
package
java.lang
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.lang.Process
;
import
java.io.FileInputStream
;
import
java.io.FileOutputStream
;
import
java.lang.ProcessBuilder.Redirect
;
import
java.lang.ProcessBuilder.Redirect
;
/**
/**
* This class is for the exclusive use of ProcessBuilder.start() to
* This class is for the exclusive use of ProcessBuilder.start() to
...
@@ -36,6 +39,9 @@ import java.lang.Process;
...
@@ -36,6 +39,9 @@ import java.lang.Process;
* @since 1.5
* @since 1.5
*/
*/
final
class
ProcessImpl
{
final
class
ProcessImpl
{
private
static
final
sun
.
misc
.
JavaIOFileDescriptorAccess
fdAccess
=
sun
.
misc
.
SharedSecrets
.
getJavaIOFileDescriptorAccess
();
private
ProcessImpl
()
{}
// Not instantiable
private
ProcessImpl
()
{}
// Not instantiable
private
static
byte
[]
toCString
(
String
s
)
{
private
static
byte
[]
toCString
(
String
s
)
{
...
@@ -54,6 +60,7 @@ final class ProcessImpl {
...
@@ -54,6 +60,7 @@ final class ProcessImpl {
static
Process
start
(
String
[]
cmdarray
,
static
Process
start
(
String
[]
cmdarray
,
java
.
util
.
Map
<
String
,
String
>
environment
,
java
.
util
.
Map
<
String
,
String
>
environment
,
String
dir
,
String
dir
,
ProcessBuilder
.
Redirect
[]
redirects
,
boolean
redirectErrorStream
)
boolean
redirectErrorStream
)
throws
IOException
throws
IOException
{
{
...
@@ -78,11 +85,61 @@ final class ProcessImpl {
...
@@ -78,11 +85,61 @@ final class ProcessImpl {
int
[]
envc
=
new
int
[
1
];
int
[]
envc
=
new
int
[
1
];
byte
[]
envBlock
=
ProcessEnvironment
.
toEnvironmentBlock
(
environment
,
envc
);
byte
[]
envBlock
=
ProcessEnvironment
.
toEnvironmentBlock
(
environment
,
envc
);
int
[]
std_fds
;
FileInputStream
f0
=
null
;
FileOutputStream
f1
=
null
;
FileOutputStream
f2
=
null
;
try
{
if
(
redirects
==
null
)
{
std_fds
=
new
int
[]
{
-
1
,
-
1
,
-
1
};
}
else
{
std_fds
=
new
int
[
3
];
if
(
redirects
[
0
]
==
Redirect
.
PIPE
)
std_fds
[
0
]
=
-
1
;
else
if
(
redirects
[
0
]
==
Redirect
.
INHERIT
)
std_fds
[
0
]
=
0
;
else
{
f0
=
new
FileInputStream
(
redirects
[
0
].
file
());
std_fds
[
0
]
=
fdAccess
.
get
(
f0
.
getFD
());
}
if
(
redirects
[
1
]
==
Redirect
.
PIPE
)
std_fds
[
1
]
=
-
1
;
else
if
(
redirects
[
1
]
==
Redirect
.
INHERIT
)
std_fds
[
1
]
=
1
;
else
{
f1
=
redirects
[
1
].
toFileOutputStream
();
std_fds
[
1
]
=
fdAccess
.
get
(
f1
.
getFD
());
}
if
(
redirects
[
2
]
==
Redirect
.
PIPE
)
std_fds
[
2
]
=
-
1
;
else
if
(
redirects
[
2
]
==
Redirect
.
INHERIT
)
std_fds
[
2
]
=
2
;
else
{
f2
=
redirects
[
2
].
toFileOutputStream
();
std_fds
[
2
]
=
fdAccess
.
get
(
f2
.
getFD
());
}
}
return
new
UNIXProcess
return
new
UNIXProcess
(
toCString
(
cmdarray
[
0
]),
(
toCString
(
cmdarray
[
0
]),
argBlock
,
args
.
length
,
argBlock
,
args
.
length
,
envBlock
,
envc
[
0
],
envBlock
,
envc
[
0
],
toCString
(
dir
),
toCString
(
dir
),
std_fds
,
redirectErrorStream
);
redirectErrorStream
);
}
finally
{
// In theory, close() can throw IOException
// (although it is rather unlikely to happen here)
try
{
if
(
f0
!=
null
)
f0
.
close
();
}
finally
{
try
{
if
(
f1
!=
null
)
f1
.
close
();
}
finally
{
if
(
f2
!=
null
)
f2
.
close
();
}
}
}
}
}
}
}
src/solaris/classes/java/lang/UNIXProcess.java.linux
浏览文件 @
095ce48d
/*
/*
*
Copyright
1995
-
200
6
Sun
Microsystems
,
Inc
.
All
Rights
Reserved
.
*
Copyright
1995
-
200
8
Sun
Microsystems
,
Inc
.
All
Rights
Reserved
.
*
DO
NOT
ALTER
OR
REMOVE
COPYRIGHT
NOTICES
OR
THIS
FILE
HEADER
.
*
DO
NOT
ALTER
OR
REMOVE
COPYRIGHT
NOTICES
OR
THIS
FILE
HEADER
.
*
*
*
This
code
is
free
software
;
you
can
redistribute
it
and
/
or
modify
it
*
This
code
is
free
software
;
you
can
redistribute
it
and
/
or
modify
it
...
@@ -34,9 +34,9 @@ import java.io.*;
...
@@ -34,9 +34,9 @@ import java.io.*;
*/
*/
final
class
UNIXProcess
extends
Process
{
final
class
UNIXProcess
extends
Process
{
private
FileDescriptor
stdin_fd
;
private
static
final
sun
.
misc
.
JavaIOFileDescriptorAccess
fdAccess
private
FileDescriptor
stdout_fd
;
=
sun
.
misc
.
SharedSecrets
.
getJavaIOFileDescriptorAccess
()
;
private
FileDescriptor
stderr_fd
;
private
int
pid
;
private
int
pid
;
private
int
exitcode
;
private
int
exitcode
;
private
boolean
hasExited
;
private
boolean
hasExited
;
...
@@ -48,14 +48,25 @@ final class UNIXProcess extends Process {
...
@@ -48,14 +48,25 @@ final class UNIXProcess extends Process {
/*
this
is
for
the
reaping
thread
*/
/*
this
is
for
the
reaping
thread
*/
private
native
int
waitForProcessExit
(
int
pid
);
private
native
int
waitForProcessExit
(
int
pid
);
/**
*
Create
a
process
using
fork
(
2
)
and
exec
(
2
).
*
*
@
param
std_fds
array
of
file
descriptors
.
Indexes
0
,
1
,
and
*
2
correspond
to
standard
input
,
standard
output
and
*
standard
error
,
respectively
.
On
input
,
a
value
of
-
1
*
means
to
create
a
pipe
to
connect
child
and
parent
*
processes
.
On
output
,
a
value
which
is
not
-
1
is
the
*
parent
pipe
fd
corresponding
to
the
pipe
which
has
*
been
created
.
An
element
of
this
array
is
-
1
on
input
*
if
and
only
if
it
is
<
em
>
not
</
em
>
-
1
on
output
.
*
@
return
the
pid
of
the
subprocess
*/
private
native
int
forkAndExec
(
byte
[]
prog
,
private
native
int
forkAndExec
(
byte
[]
prog
,
byte
[]
argBlock
,
int
argc
,
byte
[]
argBlock
,
int
argc
,
byte
[]
envBlock
,
int
envc
,
byte
[]
envBlock
,
int
envc
,
byte
[]
dir
,
byte
[]
dir
,
boolean
redirectErrorStream
,
int
[]
std_fds
,
FileDescriptor
stdin_fd
,
boolean
redirectErrorStream
)
FileDescriptor
stdout_fd
,
FileDescriptor
stderr_fd
)
throws
IOException
;
throws
IOException
;
/*
In
the
process
constructor
we
wait
on
this
gate
until
the
process
*/
/*
In
the
process
constructor
we
wait
on
this
gate
until
the
process
*/
...
@@ -100,11 +111,9 @@ final class UNIXProcess extends Process {
...
@@ -100,11 +111,9 @@ final class UNIXProcess extends Process {
final
byte
[]
argBlock
,
final
int
argc
,
final
byte
[]
argBlock
,
final
int
argc
,
final
byte
[]
envBlock
,
final
int
envc
,
final
byte
[]
envBlock
,
final
int
envc
,
final
byte
[]
dir
,
final
byte
[]
dir
,
final
int
[]
std_fds
,
final
boolean
redirectErrorStream
)
final
boolean
redirectErrorStream
)
throws
IOException
{
throws
IOException
{
stdin_fd
=
new
FileDescriptor
();
stdout_fd
=
new
FileDescriptor
();
stderr_fd
=
new
FileDescriptor
();
final
Gate
gate
=
new
Gate
();
final
Gate
gate
=
new
Gate
();
/*
/*
...
@@ -117,8 +126,8 @@ final class UNIXProcess extends Process {
...
@@ -117,8 +126,8 @@ final class UNIXProcess extends Process {
*/
*/
java.security.AccessController.doPrivileged(
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction
() {
new java.security.PrivilegedAction<Void>
() {
public Object
run() {
public Void
run() {
Thread t = new Thread("process reaper") {
Thread t = new Thread("process reaper") {
public void run() {
public void run() {
try {
try {
...
@@ -126,24 +135,43 @@ final class UNIXProcess extends Process {
...
@@ -126,24 +135,43 @@ final class UNIXProcess extends Process {
argBlock, argc,
argBlock, argc,
envBlock, envc,
envBlock, envc,
dir,
dir,
redirectErrorStream
,
std_fds
,
stdin_fd, stdout_fd, stderr_fd
);
redirectErrorStream
);
} catch (IOException e) {
} catch (IOException e) {
gate.setException(e); /*remember to rethrow later*/
gate.setException(e); /*remember to rethrow later*/
gate.exit();
gate.exit();
return;
return;
}
}
java.security.AccessController.doPrivileged(
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
new java.security.PrivilegedAction<Void>() {
public Object run() {
public Void run() {
stdin_stream = new BufferedOutputStream(new
if (std_fds[0] == -1)
FileOutputStream(stdin_fd));
stdin_stream = new ProcessBuilder.NullOutputStream();
stdout_stream = new BufferedInputStream(new
else {
FileInputStream(stdout_fd));
FileDescriptor stdin_fd = new FileDescriptor();
fdAccess.set(stdin_fd, std_fds[0]);
stdin_stream = new BufferedOutputStream(
new FileOutputStream(stdin_fd));
}
if (std_fds[1] == -1)
stdout_stream = new ProcessBuilder.NullInputStream();
else {
FileDescriptor stdout_fd = new FileDescriptor();
fdAccess.set(stdout_fd, std_fds[1]);
stdout_stream = new BufferedInputStream(
new FileInputStream(stdout_fd));
}
if (std_fds[2] == -1)
stderr_stream = new ProcessBuilder.NullInputStream();
else {
FileDescriptor stderr_fd = new FileDescriptor();
fdAccess.set(stderr_fd, std_fds[2]);
stderr_stream = new FileInputStream(stderr_fd);
stderr_stream = new FileInputStream(stderr_fd);
return null;
}
}
});
return null; }});
gate.exit(); /* exit from constructor */
gate.exit(); /* exit from constructor */
int res = waitForProcessExit(pid);
int res = waitForProcessExit(pid);
synchronized (UNIXProcess.this) {
synchronized (UNIXProcess.this) {
...
@@ -155,9 +183,7 @@ final class UNIXProcess extends Process {
...
@@ -155,9 +183,7 @@ final class UNIXProcess extends Process {
};
};
t.setDaemon(true);
t.setDaemon(true);
t.start();
t.start();
return null;
return null; }});
}
});
gate.waitForExit();
gate.waitForExit();
IOException e = gate.getException();
IOException e = gate.getException();
if (e != null)
if (e != null)
...
...
src/solaris/classes/java/lang/UNIXProcess.java.solaris
浏览文件 @
095ce48d
/*
/*
*
Copyright
1995
-
200
6
Sun
Microsystems
,
Inc
.
All
Rights
Reserved
.
*
Copyright
1995
-
200
8
Sun
Microsystems
,
Inc
.
All
Rights
Reserved
.
*
DO
NOT
ALTER
OR
REMOVE
COPYRIGHT
NOTICES
OR
THIS
FILE
HEADER
.
*
DO
NOT
ALTER
OR
REMOVE
COPYRIGHT
NOTICES
OR
THIS
FILE
HEADER
.
*
*
*
This
code
is
free
software
;
you
can
redistribute
it
and
/
or
modify
it
*
This
code
is
free
software
;
you
can
redistribute
it
and
/
or
modify
it
...
@@ -33,59 +33,85 @@ import java.io.*;
...
@@ -33,59 +33,85 @@ import java.io.*;
*/
*/
final
class
UNIXProcess
extends
Process
{
final
class
UNIXProcess
extends
Process
{
private
FileDescriptor
stdin_fd
;
private
static
final
sun
.
misc
.
JavaIOFileDescriptorAccess
fdAccess
private
FileDescriptor
stdout_fd
;
=
sun
.
misc
.
SharedSecrets
.
getJavaIOFileDescriptorAccess
()
;
private
FileDescriptor
stderr_fd
;
private
int
pid
;
private
final
int
pid
;
private
int
exitcode
;
private
int
exitcode
;
private
boolean
hasExited
;
private
boolean
hasExited
;
private
OutputStream
stdin_stream
;
private
OutputStream
stdin_stream
;
private
Buffered
InputStream
stdout_stream
;
private
InputStream
stdout_stream
;
private
DeferredCloseInputStream
stdout_inner_stream
;
private
DeferredCloseInputStream
stdout_inner_stream
;
private
DeferredClose
InputStream
stderr_stream
;
private
InputStream
stderr_stream
;
/*
this
is
for
the
reaping
thread
*/
/*
this
is
for
the
reaping
thread
*/
private
native
int
waitForProcessExit
(
int
pid
);
private
native
int
waitForProcessExit
(
int
pid
);
/**
*
Create
a
process
using
fork
(
2
)
and
exec
(
2
).
*
*
@
param
std_fds
array
of
file
descriptors
.
Indexes
0
,
1
,
and
*
2
correspond
to
standard
input
,
standard
output
and
*
standard
error
,
respectively
.
On
input
,
a
value
of
-
1
*
means
to
create
a
pipe
to
connect
child
and
parent
*
processes
.
On
output
,
a
value
which
is
not
-
1
is
the
*
parent
pipe
fd
corresponding
to
the
pipe
which
has
*
been
created
.
An
element
of
this
array
is
-
1
on
input
*
if
and
only
if
it
is
<
em
>
not
</
em
>
-
1
on
output
.
*
@
return
the
pid
of
the
subprocess
*/
private
native
int
forkAndExec
(
byte
[]
prog
,
private
native
int
forkAndExec
(
byte
[]
prog
,
byte
[]
argBlock
,
int
argc
,
byte
[]
argBlock
,
int
argc
,
byte
[]
envBlock
,
int
envc
,
byte
[]
envBlock
,
int
envc
,
byte
[]
dir
,
byte
[]
dir
,
boolean
redirectErrorStream
,
int
[]
std_fds
,
FileDescriptor
stdin_fd
,
boolean
redirectErrorStream
)
FileDescriptor
stdout_fd
,
FileDescriptor
stderr_fd
)
throws
IOException
;
throws
IOException
;
UNIXProcess
(
final
byte
[]
prog
,
UNIXProcess
(
final
byte
[]
prog
,
final
byte
[]
argBlock
,
int
argc
,
final
byte
[]
argBlock
,
int
argc
,
final
byte
[]
envBlock
,
int
envc
,
final
byte
[]
envBlock
,
int
envc
,
final
byte
[]
dir
,
final
byte
[]
dir
,
final
int
[]
std_fds
,
final
boolean
redirectErrorStream
)
final
boolean
redirectErrorStream
)
throws
IOException
{
throws
IOException
{
stdin_fd
=
new
FileDescriptor
();
stdout_fd
=
new
FileDescriptor
();
stderr_fd
=
new
FileDescriptor
();
pid
=
forkAndExec
(
prog
,
pid
=
forkAndExec
(
prog
,
argBlock
,
argc
,
argBlock
,
argc
,
envBlock
,
envc
,
envBlock
,
envc
,
dir
,
dir
,
redirectErrorStream
,
std_fds
,
stdin_fd
,
stdout_fd
,
stderr_fd
);
redirectErrorStream
);
java
.
security
.
AccessController
.
doPrivileged
(
java
.
security
.
AccessController
.
doPrivileged
(
new
java
.
security
.
PrivilegedAction
()
{
new
java
.
security
.
PrivilegedAction
<
Void
>()
{
public
Void
run
()
{
public
Object
run
()
{
if
(
std_fds
[
0
]
==
-
1
)
stdin_stream
stdin_stream
=
new
ProcessBuilder
.
NullOutputStream
();
=
new
BufferedOutputStream
(
new
FileOutputStream
(
stdin_fd
));
else
{
FileDescriptor
stdin_fd
=
new
FileDescriptor
();
fdAccess
.
set
(
stdin_fd
,
std_fds
[
0
]);
stdin_stream
=
new
BufferedOutputStream
(
new
FileOutputStream
(
stdin_fd
));
}
if
(
std_fds
[
1
]
==
-
1
)
stdout_stream
=
new
ProcessBuilder
.
NullInputStream
();
else
{
FileDescriptor
stdout_fd
=
new
FileDescriptor
();
fdAccess
.
set
(
stdout_fd
,
std_fds
[
1
]);
stdout_inner_stream
=
new
DeferredCloseInputStream
(
stdout_fd
);
stdout_inner_stream
=
new
DeferredCloseInputStream
(
stdout_fd
);
stdout_stream
=
new
BufferedInputStream
(
stdout_inner_stream
);
stdout_stream
=
new
BufferedInputStream
(
stdout_inner_stream
);
}
if
(
std_fds
[
2
]
==
-
1
)
stderr_stream
=
new
ProcessBuilder
.
NullInputStream
();
else
{
FileDescriptor
stderr_fd
=
new
FileDescriptor
();
fdAccess
.
set
(
stderr_fd
,
std_fds
[
2
]);
stderr_stream
=
new
DeferredCloseInputStream
(
stderr_fd
);
stderr_stream
=
new
DeferredCloseInputStream
(
stderr_fd
);
return
null
;
}
}
});
return
null
;
}});
/*
/*
*
For
each
subprocess
forked
a
corresponding
reaper
thread
*
For
each
subprocess
forked
a
corresponding
reaper
thread
...
@@ -97,8 +123,7 @@ final class UNIXProcess extends Process {
...
@@ -97,8 +123,7 @@ final class UNIXProcess extends Process {
*/
*/
java.security.AccessController.doPrivileged(
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
new java.security.PrivilegedAction<Void>() { public Void run() {
public Object run() {
Thread t = new Thread("process reaper") {
Thread t = new Thread("process reaper") {
public void run() {
public void run() {
int res = waitForProcessExit(pid);
int res = waitForProcessExit(pid);
...
@@ -111,9 +136,7 @@ final class UNIXProcess extends Process {
...
@@ -111,9 +136,7 @@ final class UNIXProcess extends Process {
};
};
t.setDaemon(true);
t.setDaemon(true);
t.start();
t.start();
return null;
return null; }});
}
});
}
}
public OutputStream getOutputStream() {
public OutputStream getOutputStream() {
...
@@ -154,8 +177,11 @@ final class UNIXProcess extends Process {
...
@@ -154,8 +177,11 @@ final class UNIXProcess extends Process {
destroyProcess(pid);
destroyProcess(pid);
try {
try {
stdin_stream.close();
stdin_stream.close();
if (stdout_inner_stream != null)
stdout_inner_stream.closeDeferred(stdout_stream);
stdout_inner_stream.closeDeferred(stdout_stream);
stderr_stream.closeDeferred(stderr_stream);
if (stderr_stream instanceof DeferredCloseInputStream)
((DeferredCloseInputStream) stderr_stream)
.closeDeferred(stderr_stream);
} catch (IOException e) {
} catch (IOException e) {
// ignore
// ignore
}
}
...
...
src/solaris/native/java/lang/UNIXProcess_md.c
浏览文件 @
095ce48d
/*
/*
* Copyright 1995-200
6
Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1995-200
8
Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -491,10 +491,8 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
...
@@ -491,10 +491,8 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
jbyteArray
argBlock
,
jint
argc
,
jbyteArray
argBlock
,
jint
argc
,
jbyteArray
envBlock
,
jint
envc
,
jbyteArray
envBlock
,
jint
envc
,
jbyteArray
dir
,
jbyteArray
dir
,
jboolean
redirectErrorStream
,
jintArray
std_fds
,
jobject
stdin_fd
,
jboolean
redirectErrorStream
)
jobject
stdout_fd
,
jobject
stderr_fd
)
{
{
int
errnum
;
int
errnum
;
int
resultPid
=
-
1
;
int
resultPid
=
-
1
;
...
@@ -505,6 +503,7 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
...
@@ -505,6 +503,7 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
const
char
*
pargBlock
=
getBytes
(
env
,
argBlock
);
const
char
*
pargBlock
=
getBytes
(
env
,
argBlock
);
const
char
*
penvBlock
=
getBytes
(
env
,
envBlock
);
const
char
*
penvBlock
=
getBytes
(
env
,
envBlock
);
const
char
*
pdir
=
getBytes
(
env
,
dir
);
const
char
*
pdir
=
getBytes
(
env
,
dir
);
jint
*
fds
=
NULL
;
in
[
0
]
=
in
[
1
]
=
out
[
0
]
=
out
[
1
]
=
err
[
0
]
=
err
[
1
]
=
fail
[
0
]
=
fail
[
1
]
=
-
1
;
in
[
0
]
=
in
[
1
]
=
out
[
0
]
=
out
[
1
]
=
err
[
0
]
=
err
[
1
]
=
fail
[
0
]
=
fail
[
1
]
=
-
1
;
...
@@ -527,9 +526,13 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
...
@@ -527,9 +526,13 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
initVectorFromBlock
(
envv
,
penvBlock
,
envc
);
initVectorFromBlock
(
envv
,
penvBlock
,
envc
);
}
}
if
((
pipe
(
in
)
<
0
)
||
assert
(
std_fds
!=
NULL
);
(
pipe
(
out
)
<
0
)
||
fds
=
(
*
env
)
->
GetIntArrayElements
(
env
,
std_fds
,
NULL
);
(
pipe
(
err
)
<
0
)
||
if
(
fds
==
NULL
)
goto
Catch
;
if
((
fds
[
0
]
==
-
1
&&
pipe
(
in
)
<
0
)
||
(
fds
[
1
]
==
-
1
&&
pipe
(
out
)
<
0
)
||
(
fds
[
2
]
==
-
1
&&
pipe
(
err
)
<
0
)
||
(
pipe
(
fail
)
<
0
))
{
(
pipe
(
fail
)
<
0
))
{
throwIOException
(
env
,
errno
,
"Bad file descriptor"
);
throwIOException
(
env
,
errno
,
"Bad file descriptor"
);
goto
Catch
;
goto
Catch
;
...
@@ -544,23 +547,26 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
...
@@ -544,23 +547,26 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
if
(
resultPid
==
0
)
{
if
(
resultPid
==
0
)
{
/* Child process */
/* Child process */
/* Close the parent sides of the pipe.
/* Close the parent sides of the pipes.
Give the child sides of the pipes the right fileno's.
Closing pipe fds here is redundant, since closeDescriptors()
Closing pipe fds here is redundant, since closeDescriptors()
would do it anyways, but a little paranoia is a good thing. */
would do it anyways, but a little paranoia is a good thing. */
closeSafely
(
in
[
1
]);
closeSafely
(
out
[
0
]);
closeSafely
(
err
[
0
]);
closeSafely
(
fail
[
0
]);
/* Give the child sides of the pipes the right fileno's. */
/* Note: it is possible for in[0] == 0 */
/* Note: it is possible for in[0] == 0 */
close
(
in
[
1
]);
moveDescriptor
(
in
[
0
]
!=
-
1
?
in
[
0
]
:
fds
[
0
],
STDIN_FILENO
);
moveDescriptor
(
in
[
0
],
STDIN_FILENO
);
moveDescriptor
(
out
[
1
]
!=
-
1
?
out
[
1
]
:
fds
[
1
],
STDOUT_FILENO
);
close
(
out
[
0
]);
moveDescriptor
(
out
[
1
],
STDOUT_FILENO
);
close
(
err
[
0
]);
if
(
redirectErrorStream
)
{
if
(
redirectErrorStream
)
{
close
(
err
[
1
]);
close
Safely
(
err
[
1
]);
dup2
(
STDOUT_FILENO
,
STDERR_FILENO
);
dup2
(
STDOUT_FILENO
,
STDERR_FILENO
);
}
else
{
}
else
{
moveDescriptor
(
err
[
1
],
STDERR_FILENO
);
moveDescriptor
(
err
[
1
]
!=
-
1
?
err
[
1
]
:
fds
[
2
]
,
STDERR_FILENO
);
}
}
close
(
fail
[
0
]);
moveDescriptor
(
fail
[
1
],
FAIL_FILENO
);
moveDescriptor
(
fail
[
1
],
FAIL_FILENO
);
/* close everything */
/* close everything */
...
@@ -606,9 +612,9 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
...
@@ -606,9 +612,9 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
goto
Catch
;
goto
Catch
;
}
}
(
*
env
)
->
SetIntField
(
env
,
stdin_fd
,
IO_fd_fdID
,
in
[
1
])
;
fds
[
0
]
=
(
in
[
1
]
!=
-
1
)
?
in
[
1
]
:
-
1
;
(
*
env
)
->
SetIntField
(
env
,
stdout_fd
,
IO_fd_fdID
,
out
[
0
])
;
fds
[
1
]
=
(
out
[
0
]
!=
-
1
)
?
out
[
0
]
:
-
1
;
(
*
env
)
->
SetIntField
(
env
,
stderr_fd
,
IO_fd_fdID
,
err
[
0
])
;
fds
[
2
]
=
(
err
[
0
]
!=
-
1
)
?
err
[
0
]
:
-
1
;
Finally:
Finally:
/* Always clean up the child's side of the pipes */
/* Always clean up the child's side of the pipes */
...
@@ -628,6 +634,9 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
...
@@ -628,6 +634,9 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
releaseBytes
(
env
,
envBlock
,
penvBlock
);
releaseBytes
(
env
,
envBlock
,
penvBlock
);
releaseBytes
(
env
,
dir
,
pdir
);
releaseBytes
(
env
,
dir
,
pdir
);
if
(
fds
!=
NULL
)
(
*
env
)
->
ReleaseIntArrayElements
(
env
,
std_fds
,
fds
,
0
);
return
resultPid
;
return
resultPid
;
Catch:
Catch:
...
...
src/windows/classes/java/io/FileDescriptor.java
浏览文件 @
095ce48d
...
@@ -29,17 +29,14 @@ import java.util.concurrent.atomic.AtomicInteger;
...
@@ -29,17 +29,14 @@ import java.util.concurrent.atomic.AtomicInteger;
/**
/**
* Instances of the file descriptor class serve as an opaque handle
* Instances of the file descriptor class serve as an opaque handle
* to the underlying machine-specific structure representing an open
* to the underlying machine-specific structure representing an
* file, an open socket, or another source or sink of bytes. The
* open file, an open socket, or another source or sink of bytes.
* main practical use for a file descriptor is to create a
* The main practical use for a file descriptor is to create a
* <code>FileInputStream</code> or <code>FileOutputStream</code> to
* {@link FileInputStream} or {@link FileOutputStream} to contain it.
* contain it.
*
* <p>
* <p>Applications should not create their own file descriptors.
* Applications should not create their own file descriptors.
*
*
* @author Pavani Diwanji
* @author Pavani Diwanji
* @see java.io.FileInputStream
* @see java.io.FileOutputStream
* @since JDK1.0
* @since JDK1.0
*/
*/
public
final
class
FileDescriptor
{
public
final
class
FileDescriptor
{
...
@@ -81,6 +78,14 @@ public final class FileDescriptor {
...
@@ -81,6 +78,14 @@ public final class FileDescriptor {
public
int
get
(
FileDescriptor
obj
)
{
public
int
get
(
FileDescriptor
obj
)
{
return
obj
.
fd
;
return
obj
.
fd
;
}
}
public
void
setHandle
(
FileDescriptor
obj
,
long
handle
)
{
obj
.
handle
=
handle
;
}
public
long
getHandle
(
FileDescriptor
obj
)
{
return
obj
.
handle
;
}
}
}
);
);
}
}
...
@@ -88,7 +93,7 @@ public final class FileDescriptor {
...
@@ -88,7 +93,7 @@ public final class FileDescriptor {
/**
/**
* A handle to the standard input stream. Usually, this file
* A handle to the standard input stream. Usually, this file
* descriptor is not used directly, but rather via the input stream
* descriptor is not used directly, but rather via the input stream
* known as
<code>System.in</code>
.
* known as
{@code System.in}
.
*
*
* @see java.lang.System#in
* @see java.lang.System#in
*/
*/
...
@@ -97,7 +102,7 @@ public final class FileDescriptor {
...
@@ -97,7 +102,7 @@ public final class FileDescriptor {
/**
/**
* A handle to the standard output stream. Usually, this file
* A handle to the standard output stream. Usually, this file
* descriptor is not used directly, but rather via the output stream
* descriptor is not used directly, but rather via the output stream
* known as
<code>System.out</code>
.
* known as
{@code System.out}
.
* @see java.lang.System#out
* @see java.lang.System#out
*/
*/
public
static
final
FileDescriptor
out
=
standardStream
(
1
);
public
static
final
FileDescriptor
out
=
standardStream
(
1
);
...
@@ -105,7 +110,7 @@ public final class FileDescriptor {
...
@@ -105,7 +110,7 @@ public final class FileDescriptor {
/**
/**
* A handle to the standard error stream. Usually, this file
* A handle to the standard error stream. Usually, this file
* descriptor is not used directly, but rather via the output stream
* descriptor is not used directly, but rather via the output stream
* known as
<code>System.err</code>
.
* known as
{@code System.err}
.
*
*
* @see java.lang.System#err
* @see java.lang.System#err
*/
*/
...
@@ -114,9 +119,9 @@ public final class FileDescriptor {
...
@@ -114,9 +119,9 @@ public final class FileDescriptor {
/**
/**
* Tests if this file descriptor object is valid.
* Tests if this file descriptor object is valid.
*
*
* @return
<code>true</code>
if the file descriptor object represents a
* @return
{@code true}
if the file descriptor object represents a
* valid, open file, socket, or other active I/O connection;
* valid, open file, socket, or other active I/O connection;
*
<code>false</code>
otherwise.
*
{@code false}
otherwise.
*/
*/
public
boolean
valid
()
{
public
boolean
valid
()
{
return
((
handle
!=
-
1
)
||
(
fd
!=
-
1
));
return
((
handle
!=
-
1
)
||
(
fd
!=
-
1
));
...
...
src/windows/classes/java/lang/ProcessImpl.java
浏览文件 @
095ce48d
...
@@ -25,7 +25,16 @@
...
@@ -25,7 +25,16 @@
package
java.lang
;
package
java.lang
;
import
java.io.*
;
import
java.io.IOException
;
import
java.io.File
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.io.FileInputStream
;
import
java.io.FileOutputStream
;
import
java.io.FileDescriptor
;
import
java.io.BufferedInputStream
;
import
java.io.BufferedOutputStream
;
import
java.lang.ProcessBuilder.Redirect
;
/* This class is for the exclusive use of ProcessBuilder.start() to
/* This class is for the exclusive use of ProcessBuilder.start() to
* create new processes.
* create new processes.
...
@@ -35,30 +44,82 @@ import java.io.*;
...
@@ -35,30 +44,82 @@ import java.io.*;
*/
*/
final
class
ProcessImpl
extends
Process
{
final
class
ProcessImpl
extends
Process
{
private
static
final
sun
.
misc
.
JavaIOFileDescriptorAccess
fdAccess
=
sun
.
misc
.
SharedSecrets
.
getJavaIOFileDescriptorAccess
();
// System-dependent portion of ProcessBuilder.start()
// System-dependent portion of ProcessBuilder.start()
static
Process
start
(
String
cmdarray
[],
static
Process
start
(
String
cmdarray
[],
java
.
util
.
Map
<
String
,
String
>
environment
,
java
.
util
.
Map
<
String
,
String
>
environment
,
String
dir
,
String
dir
,
ProcessBuilder
.
Redirect
[]
redirects
,
boolean
redirectErrorStream
)
boolean
redirectErrorStream
)
throws
IOException
throws
IOException
{
{
String
envblock
=
ProcessEnvironment
.
toEnvironmentBlock
(
environment
);
String
envblock
=
ProcessEnvironment
.
toEnvironmentBlock
(
environment
);
return
new
ProcessImpl
(
cmdarray
,
envblock
,
dir
,
redirectErrorStream
);
FileInputStream
f0
=
null
;
FileOutputStream
f1
=
null
;
FileOutputStream
f2
=
null
;
try
{
long
[]
stdHandles
;
if
(
redirects
==
null
)
{
stdHandles
=
new
long
[]
{
-
1L
,
-
1L
,
-
1L
};
}
else
{
stdHandles
=
new
long
[
3
];
if
(
redirects
[
0
]
==
Redirect
.
PIPE
)
stdHandles
[
0
]
=
-
1L
;
else
if
(
redirects
[
0
]
==
Redirect
.
INHERIT
)
stdHandles
[
0
]
=
fdAccess
.
getHandle
(
FileDescriptor
.
in
);
else
{
f0
=
new
FileInputStream
(
redirects
[
0
].
file
());
stdHandles
[
0
]
=
fdAccess
.
getHandle
(
f0
.
getFD
());
}
if
(
redirects
[
1
]
==
Redirect
.
PIPE
)
stdHandles
[
1
]
=
-
1L
;
else
if
(
redirects
[
1
]
==
Redirect
.
INHERIT
)
stdHandles
[
1
]
=
fdAccess
.
getHandle
(
FileDescriptor
.
out
);
else
{
f1
=
redirects
[
1
].
toFileOutputStream
();
stdHandles
[
1
]
=
fdAccess
.
getHandle
(
f1
.
getFD
());
}
if
(
redirects
[
2
]
==
Redirect
.
PIPE
)
stdHandles
[
2
]
=
-
1L
;
else
if
(
redirects
[
2
]
==
Redirect
.
INHERIT
)
stdHandles
[
2
]
=
fdAccess
.
getHandle
(
FileDescriptor
.
err
);
else
{
f2
=
redirects
[
2
].
toFileOutputStream
();
stdHandles
[
2
]
=
fdAccess
.
getHandle
(
f2
.
getFD
());
}
}
return
new
ProcessImpl
(
cmdarray
,
envblock
,
dir
,
stdHandles
,
redirectErrorStream
);
}
finally
{
// In theory, close() can throw IOException
// (although it is rather unlikely to happen here)
try
{
if
(
f0
!=
null
)
f0
.
close
();
}
finally
{
try
{
if
(
f1
!=
null
)
f1
.
close
();
}
finally
{
if
(
f2
!=
null
)
f2
.
close
();
}
}
}
}
}
private
long
handle
=
0
;
private
long
handle
=
0
;
private
FileDescriptor
stdin_fd
;
private
FileDescriptor
stdout_fd
;
private
FileDescriptor
stderr_fd
;
private
OutputStream
stdin_stream
;
private
OutputStream
stdin_stream
;
private
InputStream
stdout_stream
;
private
InputStream
stdout_stream
;
private
InputStream
stderr_stream
;
private
InputStream
stderr_stream
;
private
ProcessImpl
(
String
cmd
[],
private
ProcessImpl
(
final
String
cmd
[],
String
envblock
,
final
String
envblock
,
String
path
,
final
String
path
,
boolean
redirectErrorStream
)
final
long
[]
stdHandles
,
final
boolean
redirectErrorStream
)
throws
IOException
throws
IOException
{
{
// Win32 CreateProcess requires cmd[0] to be normalized
// Win32 CreateProcess requires cmd[0] to be normalized
...
@@ -91,25 +152,39 @@ final class ProcessImpl extends Process {
...
@@ -91,25 +152,39 @@ final class ProcessImpl extends Process {
}
}
String
cmdstr
=
cmdbuf
.
toString
();
String
cmdstr
=
cmdbuf
.
toString
();
stdin_fd
=
new
FileDescriptor
();
handle
=
create
(
cmdstr
,
envblock
,
path
,
stdout_fd
=
new
FileDescriptor
();
stdHandles
,
redirectErrorStream
);
stderr_fd
=
new
FileDescriptor
();
handle
=
create
(
cmdstr
,
envblock
,
path
,
redirectErrorStream
,
stdin_fd
,
stdout_fd
,
stderr_fd
);
java
.
security
.
AccessController
.
doPrivileged
(
java
.
security
.
AccessController
.
doPrivileged
(
new
java
.
security
.
PrivilegedAction
()
{
new
java
.
security
.
PrivilegedAction
<
Void
>()
{
public
Object
run
()
{
public
Void
run
()
{
stdin_stream
=
if
(
stdHandles
[
0
]
==
-
1L
)
new
BufferedOutputStream
(
new
FileOutputStream
(
stdin_fd
));
stdin_stream
=
new
ProcessBuilder
.
NullOutputStream
();
stdout_stream
=
else
{
new
BufferedInputStream
(
new
FileInputStream
(
stdout_fd
));
FileDescriptor
stdin_fd
=
new
FileDescriptor
();
stderr_stream
=
fdAccess
.
setHandle
(
stdin_fd
,
stdHandles
[
0
]);
new
FileInputStream
(
stderr_fd
);
stdin_stream
=
new
BufferedOutputStream
(
return
null
;
new
FileOutputStream
(
stdin_fd
));
}
if
(
stdHandles
[
1
]
==
-
1L
)
stdout_stream
=
new
ProcessBuilder
.
NullInputStream
();
else
{
FileDescriptor
stdout_fd
=
new
FileDescriptor
();
fdAccess
.
setHandle
(
stdout_fd
,
stdHandles
[
1
]);
stdout_stream
=
new
BufferedInputStream
(
new
FileInputStream
(
stdout_fd
));
}
}
});
if
(
stdHandles
[
2
]
==
-
1L
)
stderr_stream
=
new
ProcessBuilder
.
NullInputStream
();
else
{
FileDescriptor
stderr_fd
=
new
FileDescriptor
();
fdAccess
.
setHandle
(
stderr_fd
,
stdHandles
[
2
]);
stderr_stream
=
new
FileInputStream
(
stderr_fd
);
}
return
null
;
}});
}
}
public
OutputStream
getOutputStream
()
{
public
OutputStream
getOutputStream
()
{
...
@@ -150,13 +225,30 @@ final class ProcessImpl extends Process {
...
@@ -150,13 +225,30 @@ final class ProcessImpl extends Process {
public
void
destroy
()
{
terminateProcess
(
handle
);
}
public
void
destroy
()
{
terminateProcess
(
handle
);
}
private
static
native
void
terminateProcess
(
long
handle
);
private
static
native
void
terminateProcess
(
long
handle
);
/**
* Create a process using the win32 function CreateProcess.
*
* @param cmdstr the Windows commandline
* @param envblock NUL-separated, double-NUL-terminated list of
* environment strings in VAR=VALUE form
* @param dir the working directory of the process, or null if
* inheriting the current directory from the parent process
* @param stdHandles array of windows HANDLEs. Indexes 0, 1, and
* 2 correspond to standard input, standard output and
* standard error, respectively. On input, a value of -1
* means to create a pipe to connect child and parent
* processes. On output, a value which is not -1 is the
* parent pipe handle corresponding to the pipe which has
* been created. An element of this array is -1 on input
* if and only if it is <em>not</em> -1 on output.
* @param redirectErrorStream redirectErrorStream attribute
* @return the native subprocess HANDLE returned by CreateProcess
*/
private
static
native
long
create
(
String
cmdstr
,
private
static
native
long
create
(
String
cmdstr
,
String
envblock
,
String
envblock
,
String
dir
,
String
dir
,
boolean
redirectErrorStream
,
long
[]
stdHandles
,
FileDescriptor
in_fd
,
boolean
redirectErrorStream
)
FileDescriptor
out_fd
,
FileDescriptor
err_fd
)
throws
IOException
;
throws
IOException
;
private
static
native
boolean
closeHandle
(
long
handle
);
private
static
native
boolean
closeHandle
(
long
handle
);
...
...
src/windows/native/java/lang/ProcessImpl_md.c
浏览文件 @
095ce48d
...
@@ -125,7 +125,7 @@ win32Error(JNIEnv *env, const char *functionName)
...
@@ -125,7 +125,7 @@ win32Error(JNIEnv *env, const char *functionName)
static
void
static
void
closeSafely
(
HANDLE
handle
)
closeSafely
(
HANDLE
handle
)
{
{
if
(
handle
)
if
(
handle
!=
INVALID_HANDLE_VALUE
)
CloseHandle
(
handle
);
CloseHandle
(
handle
);
}
}
...
@@ -134,23 +134,22 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
...
@@ -134,23 +134,22 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
jstring
cmd
,
jstring
cmd
,
jstring
envBlock
,
jstring
envBlock
,
jstring
dir
,
jstring
dir
,
jboolean
redirectErrorStream
,
jlongArray
stdHandles
,
jobject
in_fd
,
jboolean
redirectErrorStream
)
jobject
out_fd
,
jobject
err_fd
)
{
{
HANDLE
inRead
=
0
;
HANDLE
inRead
=
INVALID_HANDLE_VALUE
;
HANDLE
inWrite
=
0
;
HANDLE
inWrite
=
INVALID_HANDLE_VALUE
;
HANDLE
outRead
=
0
;
HANDLE
outRead
=
INVALID_HANDLE_VALUE
;
HANDLE
outWrite
=
0
;
HANDLE
outWrite
=
INVALID_HANDLE_VALUE
;
HANDLE
errRead
=
0
;
HANDLE
errRead
=
INVALID_HANDLE_VALUE
;
HANDLE
errWrite
=
0
;
HANDLE
errWrite
=
INVALID_HANDLE_VALUE
;
SECURITY_ATTRIBUTES
sa
;
SECURITY_ATTRIBUTES
sa
;
PROCESS_INFORMATION
pi
;
PROCESS_INFORMATION
pi
;
STARTUPINFO
si
;
STARTUPINFO
si
;
LPTSTR
pcmd
=
NULL
;
LPTSTR
pcmd
=
NULL
;
LPCTSTR
pdir
=
NULL
;
LPCTSTR
pdir
=
NULL
;
LPVOID
penvBlock
=
NULL
;
LPVOID
penvBlock
=
NULL
;
jlong
*
handles
=
NULL
;
jlong
ret
=
0
;
jlong
ret
=
0
;
OSVERSIONINFO
ver
;
OSVERSIONINFO
ver
;
jboolean
onNT
=
JNI_FALSE
;
jboolean
onNT
=
JNI_FALSE
;
...
@@ -161,17 +160,6 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
...
@@ -161,17 +160,6 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
if
(
ver
.
dwPlatformId
==
VER_PLATFORM_WIN32_NT
)
if
(
ver
.
dwPlatformId
==
VER_PLATFORM_WIN32_NT
)
onNT
=
JNI_TRUE
;
onNT
=
JNI_TRUE
;
sa
.
nLength
=
sizeof
(
sa
);
sa
.
lpSecurityDescriptor
=
0
;
sa
.
bInheritHandle
=
TRUE
;
if
(
!
(
CreatePipe
(
&
inRead
,
&
inWrite
,
&
sa
,
PIPE_SIZE
)
&&
CreatePipe
(
&
outRead
,
&
outWrite
,
&
sa
,
PIPE_SIZE
)
&&
CreatePipe
(
&
errRead
,
&
errWrite
,
&
sa
,
PIPE_SIZE
)))
{
win32Error
(
env
,
"CreatePipe"
);
goto
Catch
;
}
assert
(
cmd
!=
NULL
);
assert
(
cmd
!=
NULL
);
pcmd
=
(
LPTSTR
)
JNU_GetStringPlatformChars
(
env
,
cmd
,
NULL
);
pcmd
=
(
LPTSTR
)
JNU_GetStringPlatformChars
(
env
,
cmd
,
NULL
);
if
(
pcmd
==
NULL
)
goto
Catch
;
if
(
pcmd
==
NULL
)
goto
Catch
;
...
@@ -189,19 +177,62 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
...
@@ -189,19 +177,62 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
if
(
penvBlock
==
NULL
)
goto
Catch
;
if
(
penvBlock
==
NULL
)
goto
Catch
;
}
}
assert
(
stdHandles
!=
NULL
);
handles
=
(
*
env
)
->
GetLongArrayElements
(
env
,
stdHandles
,
NULL
);
if
(
handles
==
NULL
)
goto
Catch
;
memset
(
&
si
,
0
,
sizeof
(
si
));
memset
(
&
si
,
0
,
sizeof
(
si
));
si
.
cb
=
sizeof
(
si
);
si
.
cb
=
sizeof
(
si
);
si
.
dwFlags
=
STARTF_USESTDHANDLES
;
si
.
dwFlags
=
STARTF_USESTDHANDLES
;
si
.
hStdInput
=
inRead
;
si
.
hStdOutput
=
outWrite
;
si
.
hStdError
=
redirectErrorStream
?
outWrite
:
errWrite
;
sa
.
nLength
=
sizeof
(
sa
);
sa
.
lpSecurityDescriptor
=
0
;
sa
.
bInheritHandle
=
TRUE
;
if
(
handles
[
0
]
!=
(
jlong
)
-
1
)
{
si
.
hStdInput
=
(
HANDLE
)
handles
[
0
];
handles
[
0
]
=
(
jlong
)
-
1
;
}
else
{
if
(
!
CreatePipe
(
&
inRead
,
&
inWrite
,
&
sa
,
PIPE_SIZE
))
{
win32Error
(
env
,
"CreatePipe"
);
goto
Catch
;
}
si
.
hStdInput
=
inRead
;
SetHandleInformation
(
inWrite
,
HANDLE_FLAG_INHERIT
,
FALSE
);
SetHandleInformation
(
inWrite
,
HANDLE_FLAG_INHERIT
,
FALSE
);
handles
[
0
]
=
(
jlong
)
inWrite
;
}
SetHandleInformation
(
si
.
hStdInput
,
HANDLE_FLAG_INHERIT
,
TRUE
);
if
(
handles
[
1
]
!=
(
jlong
)
-
1
)
{
si
.
hStdOutput
=
(
HANDLE
)
handles
[
1
];
handles
[
1
]
=
(
jlong
)
-
1
;
}
else
{
if
(
!
CreatePipe
(
&
outRead
,
&
outWrite
,
&
sa
,
PIPE_SIZE
))
{
win32Error
(
env
,
"CreatePipe"
);
goto
Catch
;
}
si
.
hStdOutput
=
outWrite
;
SetHandleInformation
(
outRead
,
HANDLE_FLAG_INHERIT
,
FALSE
);
SetHandleInformation
(
outRead
,
HANDLE_FLAG_INHERIT
,
FALSE
);
handles
[
1
]
=
(
jlong
)
outRead
;
}
SetHandleInformation
(
si
.
hStdOutput
,
HANDLE_FLAG_INHERIT
,
TRUE
);
if
(
redirectErrorStream
)
{
si
.
hStdError
=
si
.
hStdOutput
;
handles
[
2
]
=
(
jlong
)
-
1
;
}
else
if
(
handles
[
2
]
!=
(
jlong
)
-
1
)
{
si
.
hStdError
=
(
HANDLE
)
handles
[
2
];
handles
[
2
]
=
(
jlong
)
-
1
;
}
else
{
if
(
!
CreatePipe
(
&
errRead
,
&
errWrite
,
&
sa
,
PIPE_SIZE
))
{
win32Error
(
env
,
"CreatePipe"
);
goto
Catch
;
}
si
.
hStdError
=
errWrite
;
SetHandleInformation
(
errRead
,
HANDLE_FLAG_INHERIT
,
FALSE
);
SetHandleInformation
(
errRead
,
HANDLE_FLAG_INHERIT
,
FALSE
);
handles
[
2
]
=
(
jlong
)
errRead
;
if
(
redirectErrorStream
)
}
SetHandleInformation
(
errWrite
,
HANDLE_FLAG_INHERIT
,
FALS
E
);
SetHandleInformation
(
si
.
hStdError
,
HANDLE_FLAG_INHERIT
,
TRU
E
);
if
(
onNT
)
if
(
onNT
)
processFlag
=
CREATE_NO_WINDOW
|
CREATE_UNICODE_ENVIRONMENT
;
processFlag
=
CREATE_NO_WINDOW
|
CREATE_UNICODE_ENVIRONMENT
;
...
@@ -237,9 +268,6 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
...
@@ -237,9 +268,6 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
CloseHandle
(
pi
.
hThread
);
CloseHandle
(
pi
.
hThread
);
ret
=
(
jlong
)
pi
.
hProcess
;
ret
=
(
jlong
)
pi
.
hProcess
;
(
*
env
)
->
SetLongField
(
env
,
in_fd
,
IO_handle_fdID
,
(
jlong
)
inWrite
);
(
*
env
)
->
SetLongField
(
env
,
out_fd
,
IO_handle_fdID
,
(
jlong
)
outRead
);
(
*
env
)
->
SetLongField
(
env
,
err_fd
,
IO_handle_fdID
,
(
jlong
)
errRead
);
Finally:
Finally:
/* Always clean up the child's side of the pipes */
/* Always clean up the child's side of the pipes */
...
@@ -257,6 +285,9 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
...
@@ -257,6 +285,9 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
else
else
JNU_ReleaseStringPlatformChars
(
env
,
dir
,
(
char
*
)
penvBlock
);
JNU_ReleaseStringPlatformChars
(
env
,
dir
,
(
char
*
)
penvBlock
);
}
}
if
(
handles
!=
NULL
)
(
*
env
)
->
ReleaseLongArrayElements
(
env
,
stdHandles
,
handles
,
0
);
return
ret
;
return
ret
;
Catch:
Catch:
...
...
test/java/lang/ProcessBuilder/Basic.java
浏览文件 @
095ce48d
...
@@ -25,12 +25,15 @@
...
@@ -25,12 +25,15 @@
* @test
* @test
* @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689
* @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689
* 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313
* 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313
* 6464154 6523983 6206031
* 6464154 6523983 6206031
4960438 6631352 6631966
* @summary Basic tests for Process and Environment Variable code
* @summary Basic tests for Process and Environment Variable code
* @run main/othervm Basic
* @run main/othervm Basic
* @author Martin Buchholz
* @author Martin Buchholz
*/
*/
import
java.lang.ProcessBuilder.Redirect
;
import
static
java
.
lang
.
ProcessBuilder
.
Redirect
.*;
import
java.io.*
;
import
java.io.*
;
import
java.util.*
;
import
java.util.*
;
import
java.security.*
;
import
java.security.*
;
...
@@ -257,7 +260,29 @@ public class Basic {
...
@@ -257,7 +260,29 @@ public class Basic {
public
static
class
JavaChild
{
public
static
class
JavaChild
{
public
static
void
main
(
String
args
[])
throws
Throwable
{
public
static
void
main
(
String
args
[])
throws
Throwable
{
String
action
=
args
[
0
];
String
action
=
args
[
0
];
if
(
action
.
equals
(
"System.getenv(String)"
))
{
if
(
action
.
equals
(
"testIO"
))
{
String
expected
=
"standard input"
;
char
[]
buf
=
new
char
[
expected
.
length
()+
1
];
int
n
=
new
InputStreamReader
(
System
.
in
).
read
(
buf
,
0
,
buf
.
length
);
if
(
n
!=
expected
.
length
())
System
.
exit
(
5
);
if
(!
new
String
(
buf
,
0
,
n
).
equals
(
expected
))
System
.
exit
(
5
);
System
.
err
.
print
(
"standard error"
);
System
.
out
.
print
(
"standard output"
);
}
else
if
(
action
.
equals
(
"testInheritIO"
))
{
List
<
String
>
childArgs
=
new
ArrayList
<
String
>(
javaChildArgs
);
childArgs
.
add
(
"testIO"
);
ProcessBuilder
pb
=
new
ProcessBuilder
(
childArgs
);
pb
.
inheritIO
();
ProcessResults
r
=
run
(
pb
);
if
(!
r
.
out
().
equals
(
""
))
System
.
exit
(
7
);
if
(!
r
.
err
().
equals
(
""
))
System
.
exit
(
8
);
if
(
r
.
exitValue
()
!=
0
)
System
.
exit
(
9
);
}
else
if
(
action
.
equals
(
"System.getenv(String)"
))
{
String
val
=
System
.
getenv
(
args
[
1
]);
String
val
=
System
.
getenv
(
args
[
1
]);
printUTF8
(
val
==
null
?
"null"
:
val
);
printUTF8
(
val
==
null
?
"null"
:
val
);
}
else
if
(
action
.
equals
(
"System.getenv(\\u1234)"
))
{
}
else
if
(
action
.
equals
(
"System.getenv(\\u1234)"
))
{
...
@@ -599,6 +624,333 @@ public class Basic {
...
@@ -599,6 +624,333 @@ public class Basic {
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}
}
}
static
void
checkRedirects
(
ProcessBuilder
pb
,
Redirect
in
,
Redirect
out
,
Redirect
err
)
{
equal
(
pb
.
redirectInput
(),
in
);
equal
(
pb
.
redirectOutput
(),
out
);
equal
(
pb
.
redirectError
(),
err
);
}
static
void
redirectIO
(
ProcessBuilder
pb
,
Redirect
in
,
Redirect
out
,
Redirect
err
)
{
pb
.
redirectInput
(
in
);
pb
.
redirectOutput
(
out
);
pb
.
redirectError
(
err
);
}
static
void
setFileContents
(
File
file
,
String
contents
)
{
try
{
Writer
w
=
new
FileWriter
(
file
);
w
.
write
(
contents
);
w
.
close
();
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}
}
static
String
fileContents
(
File
file
)
{
try
{
Reader
r
=
new
FileReader
(
file
);
StringBuilder
sb
=
new
StringBuilder
();
char
[]
buffer
=
new
char
[
1024
];
int
n
;
while
((
n
=
r
.
read
(
buffer
))
!=
-
1
)
sb
.
append
(
buffer
,
0
,
n
);
r
.
close
();
return
new
String
(
sb
);
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
return
""
;
}
}
static
void
testIORedirection
()
throws
Throwable
{
final
File
ifile
=
new
File
(
"ifile"
);
final
File
ofile
=
new
File
(
"ofile"
);
final
File
efile
=
new
File
(
"efile"
);
ifile
.
delete
();
ofile
.
delete
();
efile
.
delete
();
//----------------------------------------------------------------
// Check mutual inequality of different types of Redirect
//----------------------------------------------------------------
Redirect
[]
redirects
=
{
PIPE
,
INHERIT
,
Redirect
.
from
(
ifile
),
Redirect
.
to
(
ifile
),
Redirect
.
appendTo
(
ifile
),
Redirect
.
from
(
ofile
),
Redirect
.
to
(
ofile
),
Redirect
.
appendTo
(
ofile
),
};
for
(
int
i
=
0
;
i
<
redirects
.
length
;
i
++)
for
(
int
j
=
0
;
j
<
redirects
.
length
;
j
++)
equal
(
redirects
[
i
].
equals
(
redirects
[
j
]),
(
i
==
j
));
//----------------------------------------------------------------
// Check basic properties of different types of Redirect
//----------------------------------------------------------------
equal
(
PIPE
.
type
(),
Redirect
.
Type
.
PIPE
);
equal
(
PIPE
.
toString
(),
"PIPE"
);
equal
(
PIPE
.
file
(),
null
);
equal
(
INHERIT
.
type
(),
Redirect
.
Type
.
INHERIT
);
equal
(
INHERIT
.
toString
(),
"INHERIT"
);
equal
(
INHERIT
.
file
(),
null
);
equal
(
Redirect
.
from
(
ifile
).
type
(),
Redirect
.
Type
.
READ
);
equal
(
Redirect
.
from
(
ifile
).
toString
(),
"redirect to read from file \"ifile\""
);
equal
(
Redirect
.
from
(
ifile
).
file
(),
ifile
);
equal
(
Redirect
.
from
(
ifile
),
Redirect
.
from
(
ifile
));
equal
(
Redirect
.
from
(
ifile
).
hashCode
(),
Redirect
.
from
(
ifile
).
hashCode
());
equal
(
Redirect
.
to
(
ofile
).
type
(),
Redirect
.
Type
.
WRITE
);
equal
(
Redirect
.
to
(
ofile
).
toString
(),
"redirect to write to file \"ofile\""
);
equal
(
Redirect
.
to
(
ofile
).
file
(),
ofile
);
equal
(
Redirect
.
to
(
ofile
),
Redirect
.
to
(
ofile
));
equal
(
Redirect
.
to
(
ofile
).
hashCode
(),
Redirect
.
to
(
ofile
).
hashCode
());
equal
(
Redirect
.
appendTo
(
ofile
).
type
(),
Redirect
.
Type
.
APPEND
);
equal
(
Redirect
.
appendTo
(
efile
).
toString
(),
"redirect to append to file \"efile\""
);
equal
(
Redirect
.
appendTo
(
efile
).
file
(),
efile
);
equal
(
Redirect
.
appendTo
(
efile
),
Redirect
.
appendTo
(
efile
));
equal
(
Redirect
.
appendTo
(
efile
).
hashCode
(),
Redirect
.
appendTo
(
efile
).
hashCode
());
//----------------------------------------------------------------
// Check initial values of redirects
//----------------------------------------------------------------
List
<
String
>
childArgs
=
new
ArrayList
<
String
>(
javaChildArgs
);
childArgs
.
add
(
"testIO"
);
final
ProcessBuilder
pb
=
new
ProcessBuilder
(
childArgs
);
checkRedirects
(
pb
,
PIPE
,
PIPE
,
PIPE
);
//----------------------------------------------------------------
// Check inheritIO
//----------------------------------------------------------------
pb
.
inheritIO
();
checkRedirects
(
pb
,
INHERIT
,
INHERIT
,
INHERIT
);
//----------------------------------------------------------------
// Check setters and getters agree
//----------------------------------------------------------------
pb
.
redirectInput
(
ifile
);
equal
(
pb
.
redirectInput
().
file
(),
ifile
);
equal
(
pb
.
redirectInput
(),
Redirect
.
from
(
ifile
));
pb
.
redirectOutput
(
ofile
);
equal
(
pb
.
redirectOutput
().
file
(),
ofile
);
equal
(
pb
.
redirectOutput
(),
Redirect
.
to
(
ofile
));
pb
.
redirectError
(
efile
);
equal
(
pb
.
redirectError
().
file
(),
efile
);
equal
(
pb
.
redirectError
(),
Redirect
.
to
(
efile
));
THROWS
(
IllegalArgumentException
.
class
,
new
Fun
(){
void
f
()
{
pb
.
redirectInput
(
Redirect
.
to
(
ofile
));
}},
new
Fun
(){
void
f
()
{
pb
.
redirectInput
(
Redirect
.
appendTo
(
ofile
));
}},
new
Fun
(){
void
f
()
{
pb
.
redirectOutput
(
Redirect
.
from
(
ifile
));
}},
new
Fun
(){
void
f
()
{
pb
.
redirectError
(
Redirect
.
from
(
ifile
));
}});
THROWS
(
IOException
.
class
,
// Input file does not exist
new
Fun
(){
void
f
()
throws
Throwable
{
pb
.
start
();
}});
setFileContents
(
ifile
,
"standard input"
);
//----------------------------------------------------------------
// Writing to non-existent files
//----------------------------------------------------------------
{
ProcessResults
r
=
run
(
pb
);
equal
(
r
.
exitValue
(),
0
);
equal
(
fileContents
(
ofile
),
"standard output"
);
equal
(
fileContents
(
efile
),
"standard error"
);
equal
(
r
.
out
(),
""
);
equal
(
r
.
err
(),
""
);
ofile
.
delete
();
efile
.
delete
();
}
//----------------------------------------------------------------
// Both redirectErrorStream + redirectError
//----------------------------------------------------------------
{
pb
.
redirectErrorStream
(
true
);
ProcessResults
r
=
run
(
pb
);
equal
(
r
.
exitValue
(),
0
);
equal
(
fileContents
(
ofile
),
"standard error"
+
"standard output"
);
equal
(
fileContents
(
efile
),
""
);
equal
(
r
.
out
(),
""
);
equal
(
r
.
err
(),
""
);
ofile
.
delete
();
efile
.
delete
();
}
//----------------------------------------------------------------
// Appending to existing files
//----------------------------------------------------------------
{
setFileContents
(
ofile
,
"ofile-contents"
);
setFileContents
(
efile
,
"efile-contents"
);
pb
.
redirectOutput
(
Redirect
.
appendTo
(
ofile
));
pb
.
redirectError
(
Redirect
.
appendTo
(
efile
));
pb
.
redirectErrorStream
(
false
);
ProcessResults
r
=
run
(
pb
);
equal
(
r
.
exitValue
(),
0
);
equal
(
fileContents
(
ofile
),
"ofile-contents"
+
"standard output"
);
equal
(
fileContents
(
efile
),
"efile-contents"
+
"standard error"
);
equal
(
r
.
out
(),
""
);
equal
(
r
.
err
(),
""
);
ofile
.
delete
();
efile
.
delete
();
}
//----------------------------------------------------------------
// Replacing existing files
//----------------------------------------------------------------
{
setFileContents
(
ofile
,
"ofile-contents"
);
setFileContents
(
efile
,
"efile-contents"
);
pb
.
redirectOutput
(
ofile
);
pb
.
redirectError
(
Redirect
.
to
(
efile
));
ProcessResults
r
=
run
(
pb
);
equal
(
r
.
exitValue
(),
0
);
equal
(
fileContents
(
ofile
),
"standard output"
);
equal
(
fileContents
(
efile
),
"standard error"
);
equal
(
r
.
out
(),
""
);
equal
(
r
.
err
(),
""
);
ofile
.
delete
();
efile
.
delete
();
}
//----------------------------------------------------------------
// Appending twice to the same file?
//----------------------------------------------------------------
{
setFileContents
(
ofile
,
"ofile-contents"
);
setFileContents
(
efile
,
"efile-contents"
);
Redirect
appender
=
Redirect
.
appendTo
(
ofile
);
pb
.
redirectOutput
(
appender
);
pb
.
redirectError
(
appender
);
ProcessResults
r
=
run
(
pb
);
equal
(
r
.
exitValue
(),
0
);
equal
(
fileContents
(
ofile
),
"ofile-contents"
+
"standard error"
+
"standard output"
);
equal
(
fileContents
(
efile
),
"efile-contents"
);
equal
(
r
.
out
(),
""
);
equal
(
r
.
err
(),
""
);
ifile
.
delete
();
ofile
.
delete
();
efile
.
delete
();
}
//----------------------------------------------------------------
// Testing INHERIT is harder.
// Note that this requires __FOUR__ nested JVMs involved in one test,
// if you count the harness JVM.
//----------------------------------------------------------------
{
redirectIO
(
pb
,
PIPE
,
PIPE
,
PIPE
);
List
<
String
>
command
=
pb
.
command
();
command
.
set
(
command
.
size
()
-
1
,
"testInheritIO"
);
Process
p
=
pb
.
start
();
new
PrintStream
(
p
.
getOutputStream
()).
print
(
"standard input"
);
p
.
getOutputStream
().
close
();
ProcessResults
r
=
run
(
p
);
equal
(
r
.
exitValue
(),
0
);
equal
(
r
.
out
(),
"standard output"
);
equal
(
r
.
err
(),
"standard error"
);
}
//----------------------------------------------------------------
// Test security implications of I/O redirection
//----------------------------------------------------------------
// Read access to current directory is always granted;
// So create a tmpfile for input instead.
final
File
tmpFile
=
File
.
createTempFile
(
"Basic"
,
"tmp"
);
setFileContents
(
tmpFile
,
"standard input"
);
final
Policy
policy
=
new
Policy
();
Policy
.
setPolicy
(
policy
);
System
.
setSecurityManager
(
new
SecurityManager
());
try
{
final
Permission
xPermission
=
new
FilePermission
(
"<<ALL FILES>>"
,
"execute"
);
final
Permission
rxPermission
=
new
FilePermission
(
"<<ALL FILES>>"
,
"read,execute"
);
final
Permission
wxPermission
=
new
FilePermission
(
"<<ALL FILES>>"
,
"write,execute"
);
final
Permission
rwxPermission
=
new
FilePermission
(
"<<ALL FILES>>"
,
"read,write,execute"
);
THROWS
(
SecurityException
.
class
,
new
Fun
()
{
void
f
()
throws
IOException
{
policy
.
setPermissions
(
xPermission
);
redirectIO
(
pb
,
from
(
tmpFile
),
PIPE
,
PIPE
);
pb
.
start
();}},
new
Fun
()
{
void
f
()
throws
IOException
{
policy
.
setPermissions
(
rxPermission
);
redirectIO
(
pb
,
PIPE
,
to
(
ofile
),
PIPE
);
pb
.
start
();}},
new
Fun
()
{
void
f
()
throws
IOException
{
policy
.
setPermissions
(
rxPermission
);
redirectIO
(
pb
,
PIPE
,
PIPE
,
to
(
efile
));
pb
.
start
();}});
{
policy
.
setPermissions
(
rxPermission
);
redirectIO
(
pb
,
from
(
tmpFile
),
PIPE
,
PIPE
);
ProcessResults
r
=
run
(
pb
);
equal
(
r
.
out
(),
"standard output"
);
equal
(
r
.
err
(),
"standard error"
);
}
{
policy
.
setPermissions
(
wxPermission
);
redirectIO
(
pb
,
PIPE
,
to
(
ofile
),
to
(
efile
));
Process
p
=
pb
.
start
();
new
PrintStream
(
p
.
getOutputStream
()).
print
(
"standard input"
);
p
.
getOutputStream
().
close
();
ProcessResults
r
=
run
(
p
);
policy
.
setPermissions
(
rwxPermission
);
equal
(
fileContents
(
ofile
),
"standard output"
);
equal
(
fileContents
(
efile
),
"standard error"
);
}
{
policy
.
setPermissions
(
rwxPermission
);
redirectIO
(
pb
,
from
(
tmpFile
),
to
(
ofile
),
to
(
efile
));
ProcessResults
r
=
run
(
pb
);
policy
.
setPermissions
(
rwxPermission
);
equal
(
fileContents
(
ofile
),
"standard output"
);
equal
(
fileContents
(
efile
),
"standard error"
);
}
}
finally
{
policy
.
setPermissions
(
new
RuntimePermission
(
"setSecurityManager"
));
System
.
setSecurityManager
(
null
);
tmpFile
.
delete
();
ifile
.
delete
();
ofile
.
delete
();
efile
.
delete
();
}
}
private
static
void
realMain
(
String
[]
args
)
throws
Throwable
{
private
static
void
realMain
(
String
[]
args
)
throws
Throwable
{
if
(
Windows
.
is
())
if
(
Windows
.
is
())
System
.
out
.
println
(
"This appears to be a Windows system."
);
System
.
out
.
println
(
"This appears to be a Windows system."
);
...
@@ -607,6 +959,9 @@ public class Basic {
...
@@ -607,6 +959,9 @@ public class Basic {
if
(
UnicodeOS
.
is
())
if
(
UnicodeOS
.
is
())
System
.
out
.
println
(
"This appears to be a Unicode-based OS."
);
System
.
out
.
println
(
"This appears to be a Unicode-based OS."
);
try
{
testIORedirection
();
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}
//----------------------------------------------------------------
//----------------------------------------------------------------
// Basic tests for setting, replacing and deleting envvars
// Basic tests for setting, replacing and deleting envvars
//----------------------------------------------------------------
//----------------------------------------------------------------
...
@@ -1354,7 +1709,8 @@ public class Basic {
...
@@ -1354,7 +1709,8 @@ public class Basic {
execPermission
);
execPermission
);
ProcessBuilder
pb
=
new
ProcessBuilder
(
"env"
);
ProcessBuilder
pb
=
new
ProcessBuilder
(
"env"
);
pb
.
environment
().
put
(
"foo"
,
"bar"
);
pb
.
environment
().
put
(
"foo"
,
"bar"
);
pb
.
start
();
Process
p
=
pb
.
start
();
closeStreams
(
p
);
}
catch
(
IOException
e
)
{
// OK
}
catch
(
IOException
e
)
{
// OK
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}
...
@@ -1378,6 +1734,14 @@ public class Basic {
...
@@ -1378,6 +1734,14 @@ public class Basic {
}
}
static
void
closeStreams
(
Process
p
)
{
try
{
p
.
getOutputStream
().
close
();
p
.
getInputStream
().
close
();
p
.
getErrorStream
().
close
();
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}
}
//----------------------------------------------------------------
//----------------------------------------------------------------
// A Policy class designed to make permissions fiddling very easy.
// A Policy class designed to make permissions fiddling very easy.
//----------------------------------------------------------------
//----------------------------------------------------------------
...
@@ -1432,10 +1796,19 @@ public class Basic {
...
@@ -1432,10 +1796,19 @@ public class Basic {
}
}
}
catch
(
Throwable
t
)
{
}
catch
(
Throwable
t
)
{
throwable
=
t
;
throwable
=
t
;
}
finally
{
try
{
is
.
close
();
}
catch
(
Throwable
t
)
{
throwable
=
t
;
}
}
}
}
}
}
}
static
ProcessResults
run
(
ProcessBuilder
pb
)
{
try
{
return
run
(
pb
.
start
());
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
return
null
;
}
}
private
static
ProcessResults
run
(
Process
p
)
{
private
static
ProcessResults
run
(
Process
p
)
{
Throwable
throwable
=
null
;
Throwable
throwable
=
null
;
int
exitValue
=
-
1
;
int
exitValue
=
-
1
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录