Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
191f5068
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看板
提交
191f5068
编写于
8月 08, 2013
作者:
U
uta
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
7147084: (process) appA hangs when read output stream of appB which starts appC that runs forever
Reviewed-by: alanb, robm, martin
上级
a327a645
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
604 addition
and
126 deletion
+604
-126
src/windows/classes/java/lang/ProcessImpl.java
src/windows/classes/java/lang/ProcessImpl.java
+4
-2
src/windows/native/java/lang/ProcessImpl_md.c
src/windows/native/java/lang/ProcessImpl_md.c
+248
-124
test/java/lang/ProcessBuilder/InheritIOEHandle.java
test/java/lang/ProcessBuilder/InheritIOEHandle.java
+147
-0
test/java/lang/ProcessBuilder/SiblingIOEHandle.java
test/java/lang/ProcessBuilder/SiblingIOEHandle.java
+205
-0
未找到文件。
src/windows/classes/java/lang/ProcessImpl.java
浏览文件 @
191f5068
...
...
@@ -491,8 +491,10 @@ final class ProcessImpl extends Process {
/**
* Create a process using the win32 function CreateProcess.
* The method is synchronized due to MS kb315939 problem.
* All native handles should restore the inherit flag at the end of call.
*
* @param cmdstr the Windows commandline
* @param cmdstr the Windows command
line
* @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
...
...
@@ -508,7 +510,7 @@ final class ProcessImpl extends Process {
* @param redirectErrorStream redirectErrorStream attribute
* @return the native subprocess HANDLE returned by CreateProcess
*/
private
static
native
long
create
(
String
cmdstr
,
private
static
synchronized
native
long
create
(
String
cmdstr
,
String
envblock
,
String
dir
,
long
[]
stdHandles
,
...
...
src/windows/native/java/lang/ProcessImpl_md.c
浏览文件 @
191f5068
...
...
@@ -113,146 +113,270 @@ closeSafely(HANDLE handle)
CloseHandle
(
handle
);
}
JNIEXPORT
jlong
JNICALL
Java_java_lang_ProcessImpl_create
(
JNIEnv
*
env
,
jclass
ignored
,
jstring
cmd
,
jstring
envBlock
,
jstring
dir
,
jlongArray
stdHandles
,
jboolean
redirectErrorStream
)
static
BOOL
hasInheritFlag
(
HANDLE
handle
)
{
HANDLE
inRead
=
INVALID_HANDLE_VALUE
;
HANDLE
inWrite
=
INVALID_HANDLE_VALUE
;
HANDLE
outRead
=
INVALID_HANDLE_VALUE
;
HANDLE
outWrite
=
INVALID_HANDLE_VALUE
;
HANDLE
errRead
=
INVALID_HANDLE_VALUE
;
HANDLE
errWrite
=
INVALID_HANDLE_VALUE
;
SECURITY_ATTRIBUTES
sa
;
PROCESS_INFORMATION
pi
;
STARTUPINFOW
si
;
const
jchar
*
pcmd
=
NULL
;
const
jchar
*
pdir
=
NULL
;
const
jchar
*
penvBlock
=
NULL
;
jlong
*
handles
=
NULL
;
jlong
ret
=
0
;
DWORD
processFlag
;
assert
(
cmd
!=
NULL
);
pcmd
=
(
*
env
)
->
GetStringChars
(
env
,
cmd
,
NULL
);
if
(
pcmd
==
NULL
)
goto
Catch
;
if
(
dir
!=
0
)
{
pdir
=
(
*
env
)
->
GetStringChars
(
env
,
dir
,
NULL
);
if
(
pdir
==
NULL
)
goto
Catch
;
}
if
(
envBlock
!=
NULL
)
{
penvBlock
=
((
*
env
)
->
GetStringChars
(
env
,
envBlock
,
NULL
));
if
(
penvBlock
==
NULL
)
goto
Catch
;
DWORD
mask
;
if
(
GetHandleInformation
(
handle
,
&
mask
))
{
return
mask
&
HANDLE_FLAG_INHERIT
;
}
assert
(
stdHandles
!=
NULL
);
handles
=
(
*
env
)
->
GetLongArrayElements
(
env
,
stdHandles
,
NULL
);
if
(
handles
==
NULL
)
goto
Catch
;
memset
(
&
si
,
0
,
sizeof
(
si
));
si
.
cb
=
sizeof
(
si
);
si
.
dwFlags
=
STARTF_USESTDHANDLES
;
sa
.
nLength
=
sizeof
(
sa
);
sa
.
lpSecurityDescriptor
=
0
;
sa
.
bInheritHandle
=
TRUE
;
return
FALSE
;
}
if
(
handles
[
0
]
!=
(
jlong
)
-
1
)
{
si
.
hStdInput
=
(
HANDLE
)
handles
[
0
];
handles
[
0
]
=
(
jlong
)
-
1
;
#define HANDLE_STORAGE_SIZE 6
#define OFFSET_READ 0
#define OFFSET_WRITE 1
//long signed version of INVALID_HANDLE_VALUE
#define JAVA_INVALID_HANDLE_VALUE ((jlong) -1)
#define OPPOSITE_END(offset) (offset==OFFSET_READ ? OFFSET_WRITE : OFFSET_READ)
/* Pipe holder structure */
typedef
struct
_STDHOLDER
{
HANDLE
pipe
[
2
];
int
offset
;
}
STDHOLDER
;
/* Responsible for correct initialization of the [pHolder] structure
(that is used for handles recycling) if needs,
and appropriate setup of IOE handle [phStd] for child process based
on created pipe or Java handle. */
static
BOOL
initHolder
(
JNIEnv
*
env
,
jlong
*
pjhandles
,
/* IN OUT - the handle form Java,
that can be a file, console or undefined */
STDHOLDER
*
pHolder
,
/* OUT - initialized structure that holds pipe
handles */
HANDLE
*
phStd
/* OUT - initialized handle for child process */
)
{
/* Here we test the value from Java against invalid
handle value. We are not using INVALID_HANDLE_VALUE macro
due to double signed/unsigned and 32/64bit ambiguity.
Otherwise it will be easy to get the wrong
value 0x00000000FFFFFFFF
instead 0xFFFFFFFFFFFFFFFF. */
if
(
*
pjhandles
!=
JAVA_INVALID_HANDLE_VALUE
)
{
/* Java file or console redirection */
*
phStd
=
(
HANDLE
)
*
pjhandles
;
/* Here we set the related Java stream (Process.getXXXXStream())
to [ProcessBuilder.NullXXXXStream.INSTANCE] value.
The initial Java handle [*pjhandles] will be closed in
ANY case. It is not a handle leak. */
*
pjhandles
=
JAVA_INVALID_HANDLE_VALUE
;
}
else
{
if
(
!
CreatePipe
(
&
inRead
,
&
inWrite
,
&
sa
,
PIPE_SIZE
))
{
/* Creation of parent-child pipe */
if
(
!
CreatePipe
(
&
pHolder
->
pipe
[
OFFSET_READ
],
&
pHolder
->
pipe
[
OFFSET_WRITE
],
NULL
,
/* we would like to inherit
default process access,
instead of 'Everybody' access */
PIPE_SIZE
))
{
win32Error
(
env
,
L"CreatePipe"
);
goto
Catch
;
return
FALSE
;
}
else
{
/* [thisProcessEnd] has no the inherit flag because
the [lpPipeAttributes] param of [CreatePipe]
had the NULL value. */
HANDLE
thisProcessEnd
=
pHolder
->
pipe
[
OPPOSITE_END
(
pHolder
->
offset
)];
*
phStd
=
pHolder
->
pipe
[
pHolder
->
offset
];
*
pjhandles
=
(
jlong
)
thisProcessEnd
;
}
si
.
hStdInput
=
inRead
;
SetHandleInformation
(
inWrite
,
HANDLE_FLAG_INHERIT
,
0
);
handles
[
0
]
=
(
jlong
)
inWrite
;
}
SetHandleInformation
(
si
.
hStdInput
,
HANDLE_FLAG_INHERIT
,
HANDLE_FLAG_INHERIT
);
/* Pipe handle will be closed in the [releaseHolder] call,
file handle will be closed in Java.
The long-live handle need to restore the inherit flag,
we do it later in the [prepareIOEHandleState] call. */
SetHandleInformation
(
*
phStd
,
HANDLE_FLAG_INHERIT
,
HANDLE_FLAG_INHERIT
);
return
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
,
L"CreatePipe"
);
goto
Catch
;
/* Smart recycling of pipe handles in [pHolder]. For the failed
create process attempts, both ends of pipe need to be released.
The [complete] has the [TRUE] value in the failed attempt. */
static
void
releaseHolder
(
BOOL
complete
,
STDHOLDER
*
pHolder
)
{
closeSafely
(
pHolder
->
pipe
[
pHolder
->
offset
]);
if
(
complete
)
{
/* Error occur, close this process pipe end */
closeSafely
(
pHolder
->
pipe
[
OPPOSITE_END
(
pHolder
->
offset
)]);
}
}
/* Stores and drops the inherit flag of handles that should not
be shared with the child process by default, but can hold the
inherit flag due to MS process birth specific. */
static
void
prepareIOEHandleState
(
HANDLE
*
stdIOE
,
BOOL
*
inherit
)
{
int
i
;
for
(
i
=
0
;
i
<
HANDLE_STORAGE_SIZE
;
++
i
)
{
HANDLE
hstd
=
stdIOE
[
i
];
if
(
INVALID_HANDLE_VALUE
!=
hstd
&&
hasInheritFlag
(
hstd
))
{
/* FALSE by default */
inherit
[
i
]
=
TRUE
;
/* Java does not need implicit inheritance for IOE handles,
so we drop inherit flag that probably was installed by
previous CreateProcess call that launched current process.
We will return the handle state back after CreateProcess call.
By clearing inherit flag we prevent "greedy grandchild" birth.
The explicit inheritance for child process IOE handles is
implemented in the [initHolder] call. */
SetHandleInformation
(
hstd
,
HANDLE_FLAG_INHERIT
,
0
);
}
si
.
hStdOutput
=
outWrite
;
SetHandleInformation
(
outRead
,
HANDLE_FLAG_INHERIT
,
0
);
handles
[
1
]
=
(
jlong
)
outRead
;
}
SetHandleInformation
(
si
.
hStdOutput
,
HANDLE_FLAG_INHERIT
,
HANDLE_FLAG_INHERIT
);
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
,
L"CreatePipe"
);
goto
Catch
;
}
/* Restores the inheritance flag of handles from stored values. */
static
void
restoreIOEHandleState
(
const
HANDLE
*
stdIOE
,
const
BOOL
*
inherit
)
{
/* The set of current process standard IOE handles and
the set of child process IOE handles can intersect.
To restore the inherit flag right, we use backward
array iteration. */
int
i
;
for
(
i
=
HANDLE_STORAGE_SIZE
-
1
;
i
>=
0
;
--
i
)
if
(
INVALID_HANDLE_VALUE
!=
stdIOE
[
i
])
{
/* Restore inherit flag for any case.
The handle can be changed by explicit inheritance.*/
SetHandleInformation
(
stdIOE
[
i
],
HANDLE_FLAG_INHERIT
,
inherit
[
i
]
?
HANDLE_FLAG_INHERIT
:
0
);
}
si
.
hStdError
=
errWrite
;
SetHandleInformation
(
errRead
,
HANDLE_FLAG_INHERIT
,
0
);
handles
[
2
]
=
(
jlong
)
errRead
;
}
/* Please, read about the MS inheritance problem
http://support.microsoft.com/kb/315939
and critical section/synchronized block solution. */
static
jlong
processCreate
(
JNIEnv
*
env
,
const
jchar
*
pcmd
,
const
jchar
*
penvBlock
,
const
jchar
*
pdir
,
jlong
*
handles
,
jboolean
redirectErrorStream
)
{
jlong
ret
=
0L
;
STARTUPINFOW
si
=
{
sizeof
(
si
)};
/* Handles for which the inheritance flag must be restored. */
HANDLE
stdIOE
[
HANDLE_STORAGE_SIZE
]
=
{
/* Current process standard IOE handles: JDK-7147084 */
INVALID_HANDLE_VALUE
,
INVALID_HANDLE_VALUE
,
INVALID_HANDLE_VALUE
,
/* Child process IOE handles: JDK-6921885 */
(
HANDLE
)
handles
[
0
],
(
HANDLE
)
handles
[
1
],
(
HANDLE
)
handles
[
2
]};
BOOL
inherit
[
HANDLE_STORAGE_SIZE
]
=
{
FALSE
,
FALSE
,
FALSE
,
FALSE
,
FALSE
,
FALSE
};
{
/* Extraction of current process standard IOE handles */
DWORD
idsIOE
[
3
]
=
{
STD_INPUT_HANDLE
,
STD_OUTPUT_HANDLE
,
STD_ERROR_HANDLE
};
int
i
;
for
(
i
=
0
;
i
<
3
;
++
i
)
/* Should not be closed by CloseHandle! */
stdIOE
[
i
]
=
GetStdHandle
(
idsIOE
[
i
]);
}
SetHandleInformation
(
si
.
hStdError
,
HANDLE_FLAG_INHERIT
,
HANDLE_FLAG_INHERIT
);
processFlag
=
CREATE_NO_WINDOW
|
CREATE_UNICODE_ENVIRONMENT
;
ret
=
CreateProcessW
(
0
,
/* executable name */
(
LPWSTR
)
pcmd
,
/* command line */
0
,
/* process security attribute */
0
,
/* thread security attribute */
TRUE
,
/* inherits system handles */
processFlag
,
/* selected based on exe type */
(
LPVOID
)
penvBlock
,
/* environment block */
(
LPCWSTR
)
pdir
,
/* change to the new current directory */
&
si
,
/* (in) startup information */
&
pi
);
/* (out) process information */
if
(
!
ret
)
{
win32Error
(
env
,
L"CreateProcess"
);
goto
Catch
;
prepareIOEHandleState
(
stdIOE
,
inherit
);
{
/* Input */
STDHOLDER
holderIn
=
{{
INVALID_HANDLE_VALUE
,
INVALID_HANDLE_VALUE
},
OFFSET_READ
};
if
(
initHolder
(
env
,
&
handles
[
0
],
&
holderIn
,
&
si
.
hStdInput
))
{
/* Output */
STDHOLDER
holderOut
=
{{
INVALID_HANDLE_VALUE
,
INVALID_HANDLE_VALUE
},
OFFSET_WRITE
};
if
(
initHolder
(
env
,
&
handles
[
1
],
&
holderOut
,
&
si
.
hStdOutput
))
{
/* Error */
STDHOLDER
holderErr
=
{{
INVALID_HANDLE_VALUE
,
INVALID_HANDLE_VALUE
},
OFFSET_WRITE
};
BOOL
success
;
if
(
redirectErrorStream
)
{
si
.
hStdError
=
si
.
hStdOutput
;
/* Here we set the error stream to [ProcessBuilder.NullInputStream.INSTANCE]
value. That is in accordance with Java Doc for the redirection case.
The Java file for the [ handles[2] ] will be closed in ANY case. It is not
a handle leak. */
handles
[
2
]
=
JAVA_INVALID_HANDLE_VALUE
;
success
=
TRUE
;
}
else
{
success
=
initHolder
(
env
,
&
handles
[
2
],
&
holderErr
,
&
si
.
hStdError
);
}
if
(
success
)
{
PROCESS_INFORMATION
pi
;
DWORD
processFlag
=
CREATE_NO_WINDOW
|
CREATE_UNICODE_ENVIRONMENT
;
si
.
dwFlags
=
STARTF_USESTDHANDLES
;
if
(
!
CreateProcessW
(
NULL
,
/* executable name */
(
LPWSTR
)
pcmd
,
/* command line */
NULL
,
/* process security attribute */
NULL
,
/* thread security attribute */
TRUE
,
/* inherits system handles */
processFlag
,
/* selected based on exe type */
(
LPVOID
)
penvBlock
,
/* environment block */
(
LPCWSTR
)
pdir
,
/* change to the new current directory */
&
si
,
/* (in) startup information */
&
pi
))
/* (out) process information */
{
win32Error
(
env
,
L"CreateProcess"
);
}
else
{
closeSafely
(
pi
.
hThread
);
ret
=
(
jlong
)
pi
.
hProcess
;
}
}
releaseHolder
(
ret
==
0
,
&
holderErr
);
releaseHolder
(
ret
==
0
,
&
holderOut
);
}
releaseHolder
(
ret
==
0
,
&
holderIn
);
}
}
restoreIOEHandleState
(
stdIOE
,
inherit
);
CloseHandle
(
pi
.
hThread
);
ret
=
(
jlong
)
pi
.
hProcess
;
Finally:
/* Always clean up the child's side of the pipes */
closeSafely
(
inRead
);
closeSafely
(
outWrite
);
closeSafely
(
errWrite
);
if
(
pcmd
!=
NULL
)
(
*
env
)
->
ReleaseStringChars
(
env
,
cmd
,
pcmd
);
if
(
pdir
!=
NULL
)
(
*
env
)
->
ReleaseStringChars
(
env
,
dir
,
pdir
);
if
(
penvBlock
!=
NULL
)
(
*
env
)
->
ReleaseStringChars
(
env
,
envBlock
,
penvBlock
);
if
(
handles
!=
NULL
)
(
*
env
)
->
ReleaseLongArrayElements
(
env
,
stdHandles
,
handles
,
0
);
return
ret
;
}
Catch:
/* Clean up the parent's side of the pipes in case of failure only */
closeSafely
(
inWrite
);
closeSafely
(
outRead
);
closeSafely
(
errRead
);
goto
Finally
;
JNIEXPORT
jlong
JNICALL
Java_java_lang_ProcessImpl_create
(
JNIEnv
*
env
,
jclass
ignored
,
jstring
cmd
,
jstring
envBlock
,
jstring
dir
,
jlongArray
stdHandles
,
jboolean
redirectErrorStream
)
{
jlong
ret
=
0
;
if
(
cmd
!=
NULL
&&
stdHandles
!=
NULL
)
{
const
jchar
*
pcmd
=
(
*
env
)
->
GetStringChars
(
env
,
cmd
,
NULL
);
if
(
pcmd
!=
NULL
)
{
const
jchar
*
penvBlock
=
(
envBlock
!=
NULL
)
?
(
*
env
)
->
GetStringChars
(
env
,
envBlock
,
NULL
)
:
NULL
;
const
jchar
*
pdir
=
(
dir
!=
NULL
)
?
(
*
env
)
->
GetStringChars
(
env
,
dir
,
NULL
)
:
NULL
;
jlong
*
handles
=
(
*
env
)
->
GetLongArrayElements
(
env
,
stdHandles
,
NULL
);
if
(
handles
!=
NULL
)
{
ret
=
processCreate
(
env
,
pcmd
,
penvBlock
,
pdir
,
handles
,
redirectErrorStream
);
(
*
env
)
->
ReleaseLongArrayElements
(
env
,
stdHandles
,
handles
,
0
);
}
if
(
pdir
!=
NULL
)
(
*
env
)
->
ReleaseStringChars
(
env
,
dir
,
pdir
);
if
(
penvBlock
!=
NULL
)
(
*
env
)
->
ReleaseStringChars
(
env
,
envBlock
,
penvBlock
);
(
*
env
)
->
ReleaseStringChars
(
env
,
cmd
,
pcmd
);
}
}
return
ret
;
}
JNIEXPORT
jint
JNICALL
...
...
test/java/lang/ProcessBuilder/InheritIOEHandle.java
0 → 100644
浏览文件 @
191f5068
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 7147084
* @run main/othervm InheritIOEHandle
* @summary inherit IOE handles and MS CreateProcess limitations (kb315939)
*/
import
java.io.BufferedReader
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
public
class
InheritIOEHandle
{
private
static
enum
APP
{
B
,
C
;
}
private
static
File
stopC
=
new
File
(
".\\StopC.txt"
);
private
static
String
SIGNAL
=
"After call child process"
;
private
static
String
JAVA_EXE
=
System
.
getProperty
(
"java.home"
)
+
File
.
separator
+
"bin"
+
File
.
separator
+
"java"
;
private
static
String
[]
getCommandArray
(
String
processName
)
{
String
[]
cmdArray
=
{
JAVA_EXE
,
"-cp"
,
System
.
getProperty
(
"java.class.path"
),
InheritIOEHandle
.
class
.
getName
(),
processName
};
return
cmdArray
;
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
if
(!
System
.
getProperty
(
"os.name"
).
startsWith
(
"Windows"
))
{
return
;
}
if
(
args
.
length
>
0
)
{
APP
app
=
APP
.
valueOf
(
args
[
0
]);
switch
(
app
)
{
case
B:
performB
();
break
;
case
C:
performC
();
break
;
}
return
;
}
performA
();
}
private
static
void
performA
()
{
try
{
stopC
.
delete
();
ProcessBuilder
builder
=
new
ProcessBuilder
(
getCommandArray
(
APP
.
B
.
name
()));
builder
.
redirectErrorStream
(
true
);
Process
process
=
builder
.
start
();
process
.
getOutputStream
().
close
();
process
.
getErrorStream
().
close
();
try
(
BufferedReader
in
=
new
BufferedReader
(
new
InputStreamReader
(
process
.
getInputStream
(),
"utf-8"
)))
{
String
result
;
while
((
result
=
in
.
readLine
())
!=
null
)
{
if
(!
SIGNAL
.
equals
(
result
))
{
throw
new
Error
(
"Catastrophe in process B! Bad output."
);
}
}
}
// If JDK-7147084 is not fixed that point is unreachable.
// write signal file
stopC
.
createNewFile
();
System
.
err
.
println
(
"Read stream finished."
);
}
catch
(
IOException
ex
)
{
throw
new
Error
(
"Catastrophe in process A!"
,
ex
);
}
}
private
static
void
performB
()
{
try
{
ProcessBuilder
builder
=
new
ProcessBuilder
(
getCommandArray
(
APP
.
C
.
name
()));
Process
process
=
builder
.
start
();
process
.
getInputStream
().
close
();
process
.
getOutputStream
().
close
();
process
.
getErrorStream
().
close
();
System
.
out
.
println
(
SIGNAL
);
// JDK-7147084 subject:
// Process C inherits the [System.out] handle and
// handle close in B does not finalize the streaming for A.
// (handle reference count > 1).
}
catch
(
IOException
ex
)
{
throw
new
Error
(
"Catastrophe in process B!"
,
ex
);
}
}
private
static
void
performC
()
{
// If JDK-7147084 is not fixed the loop is 5min long.
for
(
int
i
=
0
;
i
<
5
*
60
;
++
i
)
{
try
{
Thread
.
sleep
(
1000
);
// check for sucess
if
(
stopC
.
exists
())
break
;
}
catch
(
InterruptedException
ex
)
{
// that is ok. Longer sleep - better effect.
}
}
}
}
test/java/lang/ProcessBuilder/SiblingIOEHandle.java
0 → 100644
浏览文件 @
191f5068
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 6921885
* @run main/othervm SiblingIOEHandle
* @summary inherit IOE handles and MS CreateProcess limitations (kb315939)
*/
import
java.io.BufferedReader
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
java.util.concurrent.BrokenBarrierException
;
import
java.util.concurrent.CyclicBarrier
;
public
class
SiblingIOEHandle
{
private
static
enum
APP
{
B
,
C
;
}
private
static
File
stopC
=
new
File
(
".\\StopCs.txt"
);
private
static
String
SIGNAL
=
"B child reported."
;
private
static
String
JAVA_EXE
=
System
.
getProperty
(
"java.home"
)
+
File
.
separator
+
"bin"
+
File
.
separator
+
"java"
;
private
static
String
[]
getCommandArray
(
String
processName
)
{
String
[]
cmdArray
=
{
JAVA_EXE
,
"-cp"
,
System
.
getProperty
(
"java.class.path"
),
SiblingIOEHandle
.
class
.
getName
(),
processName
};
return
cmdArray
;
}
public
static
void
main
(
String
[]
args
)
{
if
(!
System
.
getProperty
(
"os.name"
).
startsWith
(
"Windows"
))
{
return
;
}
if
(
args
.
length
>
0
)
{
APP
app
=
APP
.
valueOf
(
args
[
0
]);
switch
(
app
)
{
case
B:
performB
();
break
;
case
C:
performC
();
break
;
}
return
;
}
performA
(
true
);
performA
(
false
);
}
static
boolean
procClaunched
=
false
;
private
static
void
waitAbit
()
{
try
{
Thread
.
sleep
(
0
);
}
catch
(
InterruptedException
ex
)
{
// that was long enough
}
}
private
static
boolean
waitBarrier
(
CyclicBarrier
barrier
)
{
while
(
true
)
try
{
barrier
.
await
();
return
true
;
}
catch
(
InterruptedException
ex
)
{
continue
;
}
catch
(
BrokenBarrierException
ex
)
{
ex
.
printStackTrace
();
return
false
;
}
}
private
static
void
performA
(
boolean
fileOut
)
{
try
{
stopC
.
delete
();
ProcessBuilder
builderB
=
new
ProcessBuilder
(
getCommandArray
(
APP
.
B
.
name
()));
File
outB
=
null
;
if
(
fileOut
)
{
outB
=
new
File
(
"outB.txt"
);
builderB
.
redirectOutput
(
outB
);
}
builderB
.
redirectErrorStream
(
true
);
final
CyclicBarrier
barrier
=
new
CyclicBarrier
(
2
);
Thread
procCRunner
=
new
Thread
(
new
Runnable
()
{
@Override
public
void
run
()
{
try
{
if
(
waitBarrier
(
barrier
))
{
waitAbit
();
// Run process C next to B ASAP to make an attempt
// to capture the B-process IOE handles in C process.
Runtime
.
getRuntime
().
exec
(
getCommandArray
(
APP
.
C
.
name
()));
procClaunched
=
true
;
}
}
catch
(
IOException
ex
)
{
ex
.
printStackTrace
();
}
}
});
procCRunner
.
start
();
if
(!
waitBarrier
(
barrier
))
{
throw
new
Error
(
"Catastrophe in process A! Synchronization failed."
);
}
// Run process B first.
Process
processB
=
builderB
.
start
();
while
(
true
)
try
{
procCRunner
.
join
();
break
;
}
catch
(
InterruptedException
ex
)
{
continue
;
}
if
(!
procClaunched
)
{
throw
new
Error
(
"Catastrophe in process A! C was not launched."
);
}
processB
.
getOutputStream
().
close
();
processB
.
getErrorStream
().
close
();
if
(
fileOut
)
{
try
{
processB
.
waitFor
();
}
catch
(
InterruptedException
ex
)
{
throw
new
Error
(
"Catastrophe in process B! B hung up."
);
}
System
.
err
.
println
(
"Trying to delete [outB.txt]."
);
if
(!
outB
.
delete
())
{
throw
new
Error
(
"Greedy brother C deadlock! File share."
);
}
System
.
err
.
println
(
"Succeeded in delete [outB.txt]."
);
}
else
{
System
.
err
.
println
(
"Read stream start."
);
try
(
BufferedReader
in
=
new
BufferedReader
(
new
InputStreamReader
(
processB
.
getInputStream
(),
"utf-8"
)))
{
String
result
;
while
((
result
=
in
.
readLine
())
!=
null
)
{
if
(!
SIGNAL
.
equals
(
result
))
{
throw
new
Error
(
"Catastrophe in process B! Bad output."
);
}
}
}
System
.
err
.
println
(
"Read stream finished."
);
}
// If JDK-6921885 is not fixed that point is unreachable.
// Test timeout exception.
// write signal file to stop C process.
stopC
.
createNewFile
();
}
catch
(
IOException
ex
)
{
throw
new
Error
(
"Catastrophe in process A!"
,
ex
);
}
}
private
static
void
performB
()
{
System
.
out
.
println
(
SIGNAL
);
}
private
static
void
performC
()
{
// If JDK-7147084 is not fixed the loop is 5min long.
for
(
int
i
=
0
;
i
<
5
*
60
;
++
i
)
{
try
{
Thread
.
sleep
(
1000
);
// check for sucess
if
(
stopC
.
exists
())
break
;
}
catch
(
InterruptedException
ex
)
{
// that is ok. Longer sleep - better effect.
}
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录