author | rriggs |
Fri, 02 Sep 2016 12:30:46 -0400 | |
changeset 40738 | 86952e676976 |
parent 39061 | 0a7abfc4f4b0 |
child 44640 | 590dec7cadb4 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
30899
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
2 |
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
||
26 |
package java.lang; |
|
27 |
||
24577 | 28 |
import java.io.BufferedInputStream; |
29 |
import java.io.BufferedOutputStream; |
|
30 |
import java.io.File; |
|
31 |
import java.io.FileDescriptor; |
|
32 |
import java.io.FileInputStream; |
|
33 |
import java.io.FileOutputStream; |
|
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
34 |
import java.io.IOException; |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
35 |
import java.io.InputStream; |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
36 |
import java.io.OutputStream; |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
37 |
import java.lang.ProcessBuilder.Redirect; |
7515
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
38 |
import java.security.AccessController; |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
39 |
import java.security.PrivilegedAction; |
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
40 |
import java.util.ArrayList; |
30899
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
41 |
import java.util.concurrent.CompletableFuture; |
13149
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
42 |
import java.util.concurrent.TimeUnit; |
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
43 |
import java.util.regex.Matcher; |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
44 |
import java.util.regex.Pattern; |
34942
4b462ee18ed9
8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents:
33826
diff
changeset
|
45 |
|
32834
e1dca5fe4de3
8137056: Move SharedSecrets and interface friends out of sun.misc
chegar
parents:
31682
diff
changeset
|
46 |
import jdk.internal.misc.JavaIOFileDescriptorAccess; |
e1dca5fe4de3
8137056: Move SharedSecrets and interface friends out of sun.misc
chegar
parents:
31682
diff
changeset
|
47 |
import jdk.internal.misc.SharedSecrets; |
34942
4b462ee18ed9
8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents:
33826
diff
changeset
|
48 |
import jdk.internal.ref.CleanerFactory; |
2 | 49 |
|
50 |
/* This class is for the exclusive use of ProcessBuilder.start() to |
|
51 |
* create new processes. |
|
52 |
* |
|
53 |
* @author Martin Buchholz |
|
54 |
* @since 1.5 |
|
55 |
*/ |
|
56 |
||
57 |
final class ProcessImpl extends Process { |
|
32834
e1dca5fe4de3
8137056: Move SharedSecrets and interface friends out of sun.misc
chegar
parents:
31682
diff
changeset
|
58 |
private static final JavaIOFileDescriptorAccess fdAccess |
e1dca5fe4de3
8137056: Move SharedSecrets and interface friends out of sun.misc
chegar
parents:
31682
diff
changeset
|
59 |
= SharedSecrets.getJavaIOFileDescriptorAccess(); |
2 | 60 |
|
30899
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
61 |
// Windows platforms support a forcible kill signal. |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
62 |
static final boolean SUPPORTS_NORMAL_TERMINATION = false; |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
63 |
|
7515
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
64 |
/** |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
65 |
* Open a file for writing. If {@code append} is {@code true} then the file |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
66 |
* is opened for atomic append directly and a FileOutputStream constructed |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
67 |
* with the resulting handle. This is because a FileOutputStream created |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
68 |
* to append to a file does not open the file in a manner that guarantees |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
69 |
* that writes by the child process will be atomic. |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
70 |
*/ |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
71 |
private static FileOutputStream newFileOutputStream(File f, boolean append) |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
72 |
throws IOException |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
73 |
{ |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
74 |
if (append) { |
10903
dfb253adb28f
7059259: (process) ProcessBuilder.start permission check should be improved when redirecting output to append
alanb
parents:
7668
diff
changeset
|
75 |
String path = f.getPath(); |
7515
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
76 |
SecurityManager sm = System.getSecurityManager(); |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
77 |
if (sm != null) |
10903
dfb253adb28f
7059259: (process) ProcessBuilder.start permission check should be improved when redirecting output to append
alanb
parents:
7668
diff
changeset
|
78 |
sm.checkWrite(path); |
dfb253adb28f
7059259: (process) ProcessBuilder.start permission check should be improved when redirecting output to append
alanb
parents:
7668
diff
changeset
|
79 |
long handle = openForAtomicAppend(path); |
7515
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
80 |
final FileDescriptor fd = new FileDescriptor(); |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
81 |
fdAccess.setHandle(fd, handle); |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
82 |
return AccessController.doPrivileged( |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
83 |
new PrivilegedAction<FileOutputStream>() { |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
84 |
public FileOutputStream run() { |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
85 |
return new FileOutputStream(fd); |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
86 |
} |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
87 |
} |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
88 |
); |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
89 |
} else { |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
90 |
return new FileOutputStream(f); |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
91 |
} |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
92 |
} |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
93 |
|
2 | 94 |
// System-dependent portion of ProcessBuilder.start() |
95 |
static Process start(String cmdarray[], |
|
96 |
java.util.Map<String,String> environment, |
|
97 |
String dir, |
|
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
98 |
ProcessBuilder.Redirect[] redirects, |
2 | 99 |
boolean redirectErrorStream) |
100 |
throws IOException |
|
101 |
{ |
|
102 |
String envblock = ProcessEnvironment.toEnvironmentBlock(environment); |
|
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
103 |
|
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
104 |
FileInputStream f0 = null; |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
105 |
FileOutputStream f1 = null; |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
106 |
FileOutputStream f2 = null; |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
107 |
|
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
108 |
try { |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
109 |
long[] stdHandles; |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
110 |
if (redirects == null) { |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
111 |
stdHandles = new long[] { -1L, -1L, -1L }; |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
112 |
} else { |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
113 |
stdHandles = new long[3]; |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
114 |
|
33826
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
115 |
if (redirects[0] == Redirect.PIPE) { |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
116 |
stdHandles[0] = -1L; |
33826
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
117 |
} else if (redirects[0] == Redirect.INHERIT) { |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
118 |
stdHandles[0] = fdAccess.getHandle(FileDescriptor.in); |
33826
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
119 |
} else if (redirects[0] instanceof ProcessBuilder.RedirectPipeImpl) { |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
120 |
stdHandles[0] = fdAccess.getHandle(((ProcessBuilder.RedirectPipeImpl) redirects[0]).getFd()); |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
121 |
} else { |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
122 |
f0 = new FileInputStream(redirects[0].file()); |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
123 |
stdHandles[0] = fdAccess.getHandle(f0.getFD()); |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
124 |
} |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
125 |
|
33826
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
126 |
if (redirects[1] == Redirect.PIPE) { |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
127 |
stdHandles[1] = -1L; |
33826
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
128 |
} else if (redirects[1] == Redirect.INHERIT) { |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
129 |
stdHandles[1] = fdAccess.getHandle(FileDescriptor.out); |
33826
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
130 |
} else if (redirects[1] instanceof ProcessBuilder.RedirectPipeImpl) { |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
131 |
stdHandles[1] = fdAccess.getHandle(((ProcessBuilder.RedirectPipeImpl) redirects[1]).getFd()); |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
132 |
} else { |
7515
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
133 |
f1 = newFileOutputStream(redirects[1].file(), |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
134 |
redirects[1].append()); |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
135 |
stdHandles[1] = fdAccess.getHandle(f1.getFD()); |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
136 |
} |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
137 |
|
33826
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
138 |
if (redirects[2] == Redirect.PIPE) { |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
139 |
stdHandles[2] = -1L; |
33826
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
140 |
} else if (redirects[2] == Redirect.INHERIT) { |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
141 |
stdHandles[2] = fdAccess.getHandle(FileDescriptor.err); |
33826
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
142 |
} else if (redirects[2] instanceof ProcessBuilder.RedirectPipeImpl) { |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
143 |
stdHandles[2] = fdAccess.getHandle(((ProcessBuilder.RedirectPipeImpl) redirects[2]).getFd()); |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
144 |
} else { |
7515
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
145 |
f2 = newFileOutputStream(redirects[2].file(), |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
146 |
redirects[2].append()); |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
147 |
stdHandles[2] = fdAccess.getHandle(f2.getFD()); |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
148 |
} |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
149 |
} |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
150 |
|
33826
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
151 |
Process p = new ProcessImpl(cmdarray, envblock, dir, |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
152 |
stdHandles, redirectErrorStream); |
33826
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
153 |
if (redirects != null) { |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
154 |
// Copy the handles's if they are to be redirected to another process |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
155 |
if (stdHandles[0] >= 0 |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
156 |
&& redirects[0] instanceof ProcessBuilder.RedirectPipeImpl) { |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
157 |
fdAccess.setHandle(((ProcessBuilder.RedirectPipeImpl) redirects[0]).getFd(), |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
158 |
stdHandles[0]); |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
159 |
} |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
160 |
if (stdHandles[1] >= 0 |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
161 |
&& redirects[1] instanceof ProcessBuilder.RedirectPipeImpl) { |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
162 |
fdAccess.setHandle(((ProcessBuilder.RedirectPipeImpl) redirects[1]).getFd(), |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
163 |
stdHandles[1]); |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
164 |
} |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
165 |
if (stdHandles[2] >= 0 |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
166 |
&& redirects[2] instanceof ProcessBuilder.RedirectPipeImpl) { |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
167 |
fdAccess.setHandle(((ProcessBuilder.RedirectPipeImpl) redirects[2]).getFd(), |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
168 |
stdHandles[2]); |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
169 |
} |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
170 |
} |
a9e5f1b8ea57
8132394: (process) ProcessBuilder support for a pipeline of processes
rriggs
parents:
32834
diff
changeset
|
171 |
return p; |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
172 |
} finally { |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
173 |
// In theory, close() can throw IOException |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
174 |
// (although it is rather unlikely to happen here) |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
175 |
try { if (f0 != null) f0.close(); } |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
176 |
finally { |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
177 |
try { if (f1 != null) f1.close(); } |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
178 |
finally { if (f2 != null) f2.close(); } |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
179 |
} |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
180 |
} |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
181 |
|
2 | 182 |
} |
183 |
||
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
184 |
private static class LazyPattern { |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
185 |
// Escape-support version: |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
186 |
// "(\")((?:\\\\\\1|.)+?)\\1|([^\\s\"]+)"; |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
187 |
private static final Pattern PATTERN = |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
188 |
Pattern.compile("[^\\s\"]+|\"[^\"]*\""); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
189 |
}; |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
190 |
|
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
191 |
/* Parses the command string parameter into the executable name and |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
192 |
* program arguments. |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
193 |
* |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
194 |
* The command string is broken into tokens. The token separator is a space |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
195 |
* or quota character. The space inside quotation is not a token separator. |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
196 |
* There are no escape sequences. |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
197 |
*/ |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
198 |
private static String[] getTokensFromCommand(String command) { |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
199 |
ArrayList<String> matchList = new ArrayList<>(8); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
200 |
Matcher regexMatcher = LazyPattern.PATTERN.matcher(command); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
201 |
while (regexMatcher.find()) |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
202 |
matchList.add(regexMatcher.group()); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
203 |
return matchList.toArray(new String[matchList.size()]); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
204 |
} |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
205 |
|
18183
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
206 |
private static final int VERIFICATION_CMD_BAT = 0; |
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
207 |
private static final int VERIFICATION_WIN32 = 1; |
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
208 |
private static final int VERIFICATION_LEGACY = 2; |
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
209 |
private static final char ESCAPE_VERIFICATION[][] = { |
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
210 |
// We guarantee the only command file execution for implicit [cmd.exe] run. |
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
211 |
// http://technet.microsoft.com/en-us/library/bb490954.aspx |
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
212 |
{' ', '\t', '<', '>', '&', '|', '^'}, |
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
213 |
|
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
214 |
{' ', '\t', '<', '>'}, |
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
215 |
{' ', '\t'} |
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
216 |
}; |
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
217 |
|
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
218 |
private static String createCommandLine(int verificationType, |
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
219 |
final String executablePath, |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
220 |
final String cmd[]) |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
221 |
{ |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
222 |
StringBuilder cmdbuf = new StringBuilder(80); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
223 |
|
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
224 |
cmdbuf.append(executablePath); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
225 |
|
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
226 |
for (int i = 1; i < cmd.length; ++i) { |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
227 |
cmdbuf.append(' '); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
228 |
String s = cmd[i]; |
18183
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
229 |
if (needsEscaping(verificationType, s)) { |
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
230 |
cmdbuf.append('"').append(s); |
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
231 |
|
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
232 |
// The code protects the [java.exe] and console command line |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
233 |
// parser, that interprets the [\"] combination as an escape |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
234 |
// sequence for the ["] char. |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
235 |
// http://msdn.microsoft.com/en-us/library/17w5ykft.aspx |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
236 |
// |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
237 |
// If the argument is an FS path, doubling of the tail [\] |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
238 |
// char is not a problem for non-console applications. |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
239 |
// |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
240 |
// The [\"] sequence is not an escape sequence for the [cmd.exe] |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
241 |
// command line parser. The case of the [""] tail escape |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
242 |
// sequence could not be realized due to the argument validation |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
243 |
// procedure. |
18183
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
244 |
if ((verificationType != VERIFICATION_CMD_BAT) && s.endsWith("\\")) { |
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
245 |
cmdbuf.append('\\'); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
246 |
} |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
247 |
cmdbuf.append('"'); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
248 |
} else { |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
249 |
cmdbuf.append(s); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
250 |
} |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
251 |
} |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
252 |
return cmdbuf.toString(); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
253 |
} |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
254 |
|
16877 | 255 |
private static boolean isQuoted(boolean noQuotesInside, String arg, |
256 |
String errorMessage) { |
|
257 |
int lastPos = arg.length() - 1; |
|
258 |
if (lastPos >=1 && arg.charAt(0) == '"' && arg.charAt(lastPos) == '"') { |
|
259 |
// The argument has already been quoted. |
|
260 |
if (noQuotesInside) { |
|
261 |
if (arg.indexOf('"', 1) != lastPos) { |
|
262 |
// There is ["] inside. |
|
263 |
throw new IllegalArgumentException(errorMessage); |
|
264 |
} |
|
265 |
} |
|
266 |
return true; |
|
267 |
} |
|
268 |
if (noQuotesInside) { |
|
269 |
if (arg.indexOf('"') >= 0) { |
|
270 |
// There is ["] inside. |
|
271 |
throw new IllegalArgumentException(errorMessage); |
|
272 |
} |
|
273 |
} |
|
274 |
return false; |
|
275 |
} |
|
276 |
||
18183
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
277 |
private static boolean needsEscaping(int verificationType, String arg) { |
16877 | 278 |
// Switch off MS heuristic for internal ["]. |
279 |
// Please, use the explicit [cmd.exe] call |
|
280 |
// if you need the internal ["]. |
|
281 |
// Example: "cmd.exe", "/C", "Extended_MS_Syntax" |
|
282 |
||
283 |
// For [.exe] or [.com] file the unpaired/internal ["] |
|
284 |
// in the argument is not a problem. |
|
18183
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
285 |
boolean argIsQuoted = isQuoted( |
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
286 |
(verificationType == VERIFICATION_CMD_BAT), |
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
287 |
arg, "Argument has embedded quote, use the explicit CMD.EXE call."); |
16877 | 288 |
|
289 |
if (!argIsQuoted) { |
|
18183
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
290 |
char testEscape[] = ESCAPE_VERIFICATION[verificationType]; |
16877 | 291 |
for (int i = 0; i < testEscape.length; ++i) { |
292 |
if (arg.indexOf(testEscape[i]) >= 0) { |
|
293 |
return true; |
|
294 |
} |
|
295 |
} |
|
296 |
} |
|
297 |
return false; |
|
298 |
} |
|
299 |
||
300 |
private static String getExecutablePath(String path) |
|
301 |
throws IOException |
|
302 |
{ |
|
303 |
boolean pathIsQuoted = isQuoted(true, path, |
|
304 |
"Executable name has embedded quote, split the arguments"); |
|
305 |
||
306 |
// Win32 CreateProcess requires path to be normalized |
|
307 |
File fileToRun = new File(pathIsQuoted |
|
308 |
? path.substring(1, path.length() - 1) |
|
309 |
: path); |
|
310 |
||
311 |
// From the [CreateProcess] function documentation: |
|
312 |
// |
|
313 |
// "If the file name does not contain an extension, .exe is appended. |
|
314 |
// Therefore, if the file name extension is .com, this parameter |
|
315 |
// must include the .com extension. If the file name ends in |
|
316 |
// a period (.) with no extension, or if the file name contains a path, |
|
317 |
// .exe is not appended." |
|
318 |
// |
|
319 |
// "If the file name !does not contain a directory path!, |
|
320 |
// the system searches for the executable file in the following |
|
321 |
// sequence:..." |
|
322 |
// |
|
323 |
// In practice ANY non-existent path is extended by [.exe] extension |
|
324 |
// in the [CreateProcess] funcion with the only exception: |
|
325 |
// the path ends by (.) |
|
326 |
||
327 |
return fileToRun.getPath(); |
|
328 |
} |
|
329 |
||
330 |
||
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
331 |
private boolean isShellFile(String executablePath) { |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
332 |
String upPath = executablePath.toUpperCase(); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
333 |
return (upPath.endsWith(".CMD") || upPath.endsWith(".BAT")); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
334 |
} |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
335 |
|
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
336 |
private String quoteString(String arg) { |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
337 |
StringBuilder argbuf = new StringBuilder(arg.length() + 2); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
338 |
return argbuf.append('"').append(arg).append('"').toString(); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
339 |
} |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
340 |
|
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
341 |
|
30899
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
342 |
private final long handle; |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
343 |
private final ProcessHandle processHandle; |
2 | 344 |
private OutputStream stdin_stream; |
345 |
private InputStream stdout_stream; |
|
346 |
private InputStream stderr_stream; |
|
347 |
||
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
348 |
private ProcessImpl(String cmd[], |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
349 |
final String envblock, |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
350 |
final String path, |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
351 |
final long[] stdHandles, |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
352 |
final boolean redirectErrorStream) |
2 | 353 |
throws IOException |
354 |
{ |
|
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
355 |
String cmdstr; |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
356 |
SecurityManager security = System.getSecurityManager(); |
18183
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
357 |
boolean allowAmbiguousCommands = false; |
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
358 |
if (security == null) { |
18183
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
359 |
allowAmbiguousCommands = true; |
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
360 |
String value = System.getProperty("jdk.lang.Process.allowAmbiguousCommands"); |
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
361 |
if (value != null) |
18183
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
362 |
allowAmbiguousCommands = !"false".equalsIgnoreCase(value); |
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
363 |
} |
18183
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
364 |
if (allowAmbiguousCommands) { |
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
365 |
// Legacy mode. |
16877 | 366 |
|
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
367 |
// Normalize path if possible. |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
368 |
String executablePath = new File(cmd[0]).getPath(); |
2 | 369 |
|
18183
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
370 |
// No worry about internal, unpaired ["], and redirection/piping. |
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
371 |
if (needsEscaping(VERIFICATION_LEGACY, executablePath) ) |
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
372 |
executablePath = quoteString(executablePath); |
16877 | 373 |
|
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
374 |
cmdstr = createCommandLine( |
18183
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
375 |
//legacy mode doesn't worry about extended verification |
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
376 |
VERIFICATION_LEGACY, |
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
377 |
executablePath, |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
378 |
cmd); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
379 |
} else { |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
380 |
String executablePath; |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
381 |
try { |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
382 |
executablePath = getExecutablePath(cmd[0]); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
383 |
} catch (IllegalArgumentException e) { |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
384 |
// Workaround for the calls like |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
385 |
// Runtime.getRuntime().exec("\"C:\\Program Files\\foo\" bar") |
16877 | 386 |
|
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
387 |
// No chance to avoid CMD/BAT injection, except to do the work |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
388 |
// right from the beginning. Otherwise we have too many corner |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
389 |
// cases from |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
390 |
// Runtime.getRuntime().exec(String[] cmd [, ...]) |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
391 |
// calls with internal ["] and escape sequences. |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
392 |
|
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
393 |
// Restore original command line. |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
394 |
StringBuilder join = new StringBuilder(); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
395 |
// terminal space in command line is ok |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
396 |
for (String s : cmd) |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
397 |
join.append(s).append(' '); |
16885
d54b22d3b306
8009463: Regression test test\java\lang\Runtime\exec\ArgWithSpaceAndFinalBackslash.java failing.
uta
parents:
16877
diff
changeset
|
398 |
|
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
399 |
// Parse the command line again. |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
400 |
cmd = getTokensFromCommand(join.toString()); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
401 |
executablePath = getExecutablePath(cmd[0]); |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
402 |
|
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
403 |
// Check new executable name once more |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
404 |
if (security != null) |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
405 |
security.checkExec(executablePath); |
2 | 406 |
} |
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
407 |
|
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
408 |
// Quotation protects from interpretation of the [path] argument as |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
409 |
// start of longer path with spaces. Quotation has no influence to |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
410 |
// [.exe] extension heuristic. |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
411 |
cmdstr = createCommandLine( |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
412 |
// We need the extended verification procedure for CMD files. |
18183
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
413 |
isShellFile(executablePath) |
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
414 |
? VERIFICATION_CMD_BAT |
9749983601cf
8016046: (process) Strict validation of input should be security manager case only [win].
uta
parents:
17467
diff
changeset
|
415 |
: VERIFICATION_WIN32, |
17467
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
416 |
quoteString(executablePath), |
374c1cceefff
8012453: (process) Runtime.exec(String) fails if command contains spaces [win]
uta
parents:
16901
diff
changeset
|
417 |
cmd); |
2 | 418 |
} |
419 |
||
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
420 |
handle = create(cmdstr, envblock, path, |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
421 |
stdHandles, redirectErrorStream); |
34942
4b462ee18ed9
8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents:
33826
diff
changeset
|
422 |
// Register a cleaning function to close the handle |
4b462ee18ed9
8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents:
33826
diff
changeset
|
423 |
final long local_handle = handle; // local to prevent capture of this |
4b462ee18ed9
8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents:
33826
diff
changeset
|
424 |
CleanerFactory.cleaner().register(this, () -> closeHandle(local_handle)); |
4b462ee18ed9
8146028: Common Cleaner for finalization replacements in OpenJDK
rriggs
parents:
33826
diff
changeset
|
425 |
|
31682
c19dcf5e0b6d
8078099: (process) ProcessHandle should uniquely identify processes
rriggs
parents:
30899
diff
changeset
|
426 |
processHandle = ProcessHandleImpl.getInternal(getProcessId0(handle)); |
2 | 427 |
|
428 |
java.security.AccessController.doPrivileged( |
|
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
429 |
new java.security.PrivilegedAction<Void>() { |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
430 |
public Void run() { |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
431 |
if (stdHandles[0] == -1L) |
5787
a0af7b8e80ed
6960898: Regression due to src/share/classes/java/lang/ProcessBuilder.java changes
martin
parents:
5506
diff
changeset
|
432 |
stdin_stream = ProcessBuilder.NullOutputStream.INSTANCE; |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
433 |
else { |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
434 |
FileDescriptor stdin_fd = new FileDescriptor(); |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
435 |
fdAccess.setHandle(stdin_fd, stdHandles[0]); |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
436 |
stdin_stream = new BufferedOutputStream( |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
437 |
new FileOutputStream(stdin_fd)); |
2 | 438 |
} |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
439 |
|
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
440 |
if (stdHandles[1] == -1L) |
5787
a0af7b8e80ed
6960898: Regression due to src/share/classes/java/lang/ProcessBuilder.java changes
martin
parents:
5506
diff
changeset
|
441 |
stdout_stream = ProcessBuilder.NullInputStream.INSTANCE; |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
442 |
else { |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
443 |
FileDescriptor stdout_fd = new FileDescriptor(); |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
444 |
fdAccess.setHandle(stdout_fd, stdHandles[1]); |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
445 |
stdout_stream = new BufferedInputStream( |
39061
0a7abfc4f4b0
8155808: Process.getInputStream().skip() method is faulty
rriggs
parents:
34942
diff
changeset
|
446 |
new PipeInputStream(stdout_fd)); |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
447 |
} |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
448 |
|
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
449 |
if (stdHandles[2] == -1L) |
5787
a0af7b8e80ed
6960898: Regression due to src/share/classes/java/lang/ProcessBuilder.java changes
martin
parents:
5506
diff
changeset
|
450 |
stderr_stream = ProcessBuilder.NullInputStream.INSTANCE; |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
451 |
else { |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
452 |
FileDescriptor stderr_fd = new FileDescriptor(); |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
453 |
fdAccess.setHandle(stderr_fd, stdHandles[2]); |
39061
0a7abfc4f4b0
8155808: Process.getInputStream().skip() method is faulty
rriggs
parents:
34942
diff
changeset
|
454 |
stderr_stream = new PipeInputStream(stderr_fd); |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
455 |
} |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
456 |
|
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
457 |
return null; }}); |
2 | 458 |
} |
459 |
||
460 |
public OutputStream getOutputStream() { |
|
461 |
return stdin_stream; |
|
462 |
} |
|
463 |
||
464 |
public InputStream getInputStream() { |
|
465 |
return stdout_stream; |
|
466 |
} |
|
467 |
||
468 |
public InputStream getErrorStream() { |
|
469 |
return stderr_stream; |
|
470 |
} |
|
471 |
||
472 |
private static final int STILL_ACTIVE = getStillActive(); |
|
473 |
private static native int getStillActive(); |
|
474 |
||
475 |
public int exitValue() { |
|
476 |
int exitCode = getExitCodeProcess(handle); |
|
477 |
if (exitCode == STILL_ACTIVE) |
|
478 |
throw new IllegalThreadStateException("process has not exited"); |
|
479 |
return exitCode; |
|
480 |
} |
|
481 |
private static native int getExitCodeProcess(long handle); |
|
482 |
||
483 |
public int waitFor() throws InterruptedException { |
|
484 |
waitForInterruptibly(handle); |
|
485 |
if (Thread.interrupted()) |
|
486 |
throw new InterruptedException(); |
|
487 |
return exitValue(); |
|
488 |
} |
|
13149
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
489 |
|
2 | 490 |
private static native void waitForInterruptibly(long handle); |
491 |
||
13149
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
492 |
@Override |
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
493 |
public boolean waitFor(long timeout, TimeUnit unit) |
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
494 |
throws InterruptedException |
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
495 |
{ |
29604
f3e313c492ba
8067796: (process) Process.waitFor(timeout, unit) doesn't throw NPE if timeout is less than, or equal to zero when unit == null
rriggs
parents:
27732
diff
changeset
|
496 |
long remainingNanos = unit.toNanos(timeout); // throw NPE before other conditions |
13149
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
497 |
if (getExitCodeProcess(handle) != STILL_ACTIVE) return true; |
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
498 |
if (timeout <= 0) return false; |
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
499 |
|
27732
31d7da6e79bf
8064932: java/lang/ProcessBuilder/Basic.java: waitFor didn't take long enough
rriggs
parents:
25859
diff
changeset
|
500 |
long deadline = System.nanoTime() + remainingNanos ; |
31d7da6e79bf
8064932: java/lang/ProcessBuilder/Basic.java: waitFor didn't take long enough
rriggs
parents:
25859
diff
changeset
|
501 |
do { |
31d7da6e79bf
8064932: java/lang/ProcessBuilder/Basic.java: waitFor didn't take long enough
rriggs
parents:
25859
diff
changeset
|
502 |
// Round up to next millisecond |
31d7da6e79bf
8064932: java/lang/ProcessBuilder/Basic.java: waitFor didn't take long enough
rriggs
parents:
25859
diff
changeset
|
503 |
long msTimeout = TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L); |
31d7da6e79bf
8064932: java/lang/ProcessBuilder/Basic.java: waitFor didn't take long enough
rriggs
parents:
25859
diff
changeset
|
504 |
waitForTimeoutInterruptibly(handle, msTimeout); |
31d7da6e79bf
8064932: java/lang/ProcessBuilder/Basic.java: waitFor didn't take long enough
rriggs
parents:
25859
diff
changeset
|
505 |
if (Thread.interrupted()) |
31d7da6e79bf
8064932: java/lang/ProcessBuilder/Basic.java: waitFor didn't take long enough
rriggs
parents:
25859
diff
changeset
|
506 |
throw new InterruptedException(); |
31d7da6e79bf
8064932: java/lang/ProcessBuilder/Basic.java: waitFor didn't take long enough
rriggs
parents:
25859
diff
changeset
|
507 |
if (getExitCodeProcess(handle) != STILL_ACTIVE) { |
31d7da6e79bf
8064932: java/lang/ProcessBuilder/Basic.java: waitFor didn't take long enough
rriggs
parents:
25859
diff
changeset
|
508 |
return true; |
31d7da6e79bf
8064932: java/lang/ProcessBuilder/Basic.java: waitFor didn't take long enough
rriggs
parents:
25859
diff
changeset
|
509 |
} |
31d7da6e79bf
8064932: java/lang/ProcessBuilder/Basic.java: waitFor didn't take long enough
rriggs
parents:
25859
diff
changeset
|
510 |
remainingNanos = deadline - System.nanoTime(); |
31d7da6e79bf
8064932: java/lang/ProcessBuilder/Basic.java: waitFor didn't take long enough
rriggs
parents:
25859
diff
changeset
|
511 |
} while (remainingNanos > 0); |
31d7da6e79bf
8064932: java/lang/ProcessBuilder/Basic.java: waitFor didn't take long enough
rriggs
parents:
25859
diff
changeset
|
512 |
|
13149
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
513 |
return (getExitCodeProcess(handle) != STILL_ACTIVE); |
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
514 |
} |
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
515 |
|
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
516 |
private static native void waitForTimeoutInterruptibly( |
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
517 |
long handle, long timeout); |
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
518 |
|
30899
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
519 |
@Override |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
520 |
public void destroy() { |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
521 |
terminateProcess(handle); |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
522 |
} |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
523 |
|
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
524 |
@Override |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
525 |
public CompletableFuture<Process> onExit() { |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
526 |
return ProcessHandleImpl.completion(getPid(), false) |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
527 |
.handleAsync((exitStatus, unusedThrowable) -> this); |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
528 |
} |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
529 |
|
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
530 |
@Override |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
531 |
public ProcessHandle toHandle() { |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
532 |
SecurityManager sm = System.getSecurityManager(); |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
533 |
if (sm != null) { |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
534 |
sm.checkPermission(new RuntimePermission("manageProcess")); |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
535 |
} |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
536 |
return processHandle; |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
537 |
} |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
538 |
|
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
539 |
@Override |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
540 |
public boolean supportsNormalTermination() { |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
541 |
return ProcessImpl.SUPPORTS_NORMAL_TERMINATION; |
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
542 |
} |
13149
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
543 |
|
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
544 |
@Override |
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
545 |
public Process destroyForcibly() { |
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
546 |
destroy(); |
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
547 |
return this; |
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
548 |
} |
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
549 |
|
2 | 550 |
private static native void terminateProcess(long handle); |
551 |
||
13149
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
552 |
@Override |
24577 | 553 |
public long getPid() { |
30899
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
554 |
return processHandle.getPid(); |
24577 | 555 |
} |
556 |
||
557 |
private static native int getProcessId0(long handle); |
|
558 |
||
559 |
@Override |
|
13149
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
560 |
public boolean isAlive() { |
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
561 |
return isProcessAlive(handle); |
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
562 |
} |
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
563 |
|
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
564 |
private static native boolean isProcessAlive(long handle); |
27d52f97a5cc
4244896: (process) Provide System.getPid(), System.killProcess(String pid)
robm
parents:
10903
diff
changeset
|
565 |
|
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
566 |
/** |
40738
86952e676976
8155102: (Process) Process.toString could include pid, isAlive, exitStatus
rriggs
parents:
39061
diff
changeset
|
567 |
* The {@code toString} method returns a string consisting of |
86952e676976
8155102: (Process) Process.toString could include pid, isAlive, exitStatus
rriggs
parents:
39061
diff
changeset
|
568 |
* the native process ID of the process and the exit value of the process. |
86952e676976
8155102: (Process) Process.toString could include pid, isAlive, exitStatus
rriggs
parents:
39061
diff
changeset
|
569 |
* |
86952e676976
8155102: (Process) Process.toString could include pid, isAlive, exitStatus
rriggs
parents:
39061
diff
changeset
|
570 |
* @return a string representation of the object. |
86952e676976
8155102: (Process) Process.toString could include pid, isAlive, exitStatus
rriggs
parents:
39061
diff
changeset
|
571 |
*/ |
86952e676976
8155102: (Process) Process.toString could include pid, isAlive, exitStatus
rriggs
parents:
39061
diff
changeset
|
572 |
@Override |
86952e676976
8155102: (Process) Process.toString could include pid, isAlive, exitStatus
rriggs
parents:
39061
diff
changeset
|
573 |
public String toString() { |
86952e676976
8155102: (Process) Process.toString could include pid, isAlive, exitStatus
rriggs
parents:
39061
diff
changeset
|
574 |
int exitCode = getExitCodeProcess(handle); |
86952e676976
8155102: (Process) Process.toString could include pid, isAlive, exitStatus
rriggs
parents:
39061
diff
changeset
|
575 |
return new StringBuilder("Process[pid=").append(getPid()) |
86952e676976
8155102: (Process) Process.toString could include pid, isAlive, exitStatus
rriggs
parents:
39061
diff
changeset
|
576 |
.append(", exitValue=").append(exitCode == STILL_ACTIVE ? "\"not exited\"" : exitCode) |
86952e676976
8155102: (Process) Process.toString could include pid, isAlive, exitStatus
rriggs
parents:
39061
diff
changeset
|
577 |
.append("]").toString(); |
86952e676976
8155102: (Process) Process.toString could include pid, isAlive, exitStatus
rriggs
parents:
39061
diff
changeset
|
578 |
} |
86952e676976
8155102: (Process) Process.toString could include pid, isAlive, exitStatus
rriggs
parents:
39061
diff
changeset
|
579 |
|
86952e676976
8155102: (Process) Process.toString could include pid, isAlive, exitStatus
rriggs
parents:
39061
diff
changeset
|
580 |
/** |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
581 |
* Create a process using the win32 function CreateProcess. |
19372
e404c834f1cd
7147084: (process) appA hangs when read output stream of appB which starts appC that runs forever
uta
parents:
18183
diff
changeset
|
582 |
* The method is synchronized due to MS kb315939 problem. |
e404c834f1cd
7147084: (process) appA hangs when read output stream of appB which starts appC that runs forever
uta
parents:
18183
diff
changeset
|
583 |
* All native handles should restore the inherit flag at the end of call. |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
584 |
* |
19372
e404c834f1cd
7147084: (process) appA hangs when read output stream of appB which starts appC that runs forever
uta
parents:
18183
diff
changeset
|
585 |
* @param cmdstr the Windows command line |
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
586 |
* @param envblock NUL-separated, double-NUL-terminated list of |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
587 |
* environment strings in VAR=VALUE form |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
588 |
* @param dir the working directory of the process, or null if |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
589 |
* inheriting the current directory from the parent process |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
590 |
* @param stdHandles array of windows HANDLEs. Indexes 0, 1, and |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
591 |
* 2 correspond to standard input, standard output and |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
592 |
* standard error, respectively. On input, a value of -1 |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
593 |
* means to create a pipe to connect child and parent |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
594 |
* processes. On output, a value which is not -1 is the |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
595 |
* parent pipe handle corresponding to the pipe which has |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
596 |
* been created. An element of this array is -1 on input |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
597 |
* if and only if it is <em>not</em> -1 on output. |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
598 |
* @param redirectErrorStream redirectErrorStream attribute |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
599 |
* @return the native subprocess HANDLE returned by CreateProcess |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
600 |
*/ |
19372
e404c834f1cd
7147084: (process) appA hangs when read output stream of appB which starts appC that runs forever
uta
parents:
18183
diff
changeset
|
601 |
private static synchronized native long create(String cmdstr, |
2 | 602 |
String envblock, |
603 |
String dir, |
|
48
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
604 |
long[] stdHandles, |
dc5744ca15ea
4960438: (process) Need IO redirection API for subprocesses
martin
parents:
2
diff
changeset
|
605 |
boolean redirectErrorStream) |
2 | 606 |
throws IOException; |
607 |
||
7515
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
608 |
/** |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
609 |
* Opens a file for atomic append. The file is created if it doesn't |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
610 |
* already exist. |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
611 |
* |
30899
d2408e757489
8077350: JEP 102 Process API Updates Implementation
rriggs
parents:
29604
diff
changeset
|
612 |
* @param path the file to open or create |
7515
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
613 |
* @return the native HANDLE |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
614 |
*/ |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
615 |
private static native long openForAtomicAppend(String path) |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
616 |
throws IOException; |
43202796198e
6709457: (fc) lock/tryLock() throws IOException "Access is denied" when file opened for append [win]
alanb
parents:
5787
diff
changeset
|
617 |
|
2 | 618 |
private static native boolean closeHandle(long handle); |
619 |
} |