Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java
41161 views
1
/*
2
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
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
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
package nsk.share.jpda;
25
26
import nsk.share.*;
27
import java.io.*;
28
import java.net.*;
29
30
/**
31
* This class is used to control debugee VM process.
32
* <p>
33
* Object of this class is constructed by <code>DebugeeBinder</code>
34
* and is used as a mirror of debugee VM process.
35
* It provides abilities to launch such process,
36
* redirect standard output streams, wait for process terminates
37
* or kill the process, and so on.
38
* <p>
39
* This is an abstract class that declares abstract methods to control
40
* debugee VM process.
41
* Derived classes should implement these methods corresponding to the mode
42
* that the process should be started in (locally, remotely or manually).
43
* <p>
44
* Particular derived classes <code>nsk.share.jdi.Debugee</code> and
45
* <code>nsk.share.jdwp.Debugee</code> provides additional abilities
46
* to control debugee VM using JDI or JDWP specific features.
47
*
48
* @see DebugeeBinder
49
*
50
* @see nsk.share.jdi.Debugee
51
* @see nsk.share.jdwp.Debugee
52
*/
53
abstract public class DebugeeProcess extends FinalizableObject {
54
55
/** Default prefix for log messages. */
56
public static final String LOG_PREFIX = "binder> ";
57
public static final String DEBUGEE_STDOUT_LOG_PREFIX = "debugee.stdout> ";
58
public static final String DEBUGEE_STDERR_LOG_PREFIX = "debugee.stderr> ";
59
60
/** Messages prefix. */
61
protected String prefix = LOG_PREFIX;
62
63
/** Binder that creates this debugee process. */
64
protected DebugeeBinder binder = null;
65
66
/** Messages log from binder. */
67
protected Log log = null;
68
69
/** Communicational channel between debuger and debugee. */
70
protected IOPipe pipe = null;
71
72
/** Argument handler from binder. */
73
protected DebugeeArgumentHandler argumentHandler = null;
74
75
/** Need or not to check debuggee process termination at exit. */
76
protected boolean checkTermination = false;
77
78
/** Debugee VM process or <i>null</i> if not available. */
79
protected Process process = null;
80
81
/** Make new <code>Debugee</code> object for the given binder. */
82
protected DebugeeProcess (DebugeeBinder binder) {
83
this.binder = binder;
84
this.log = binder.getLog();
85
}
86
87
/**
88
* Return already bound ServerSocket for IOPipe connection or null.
89
*/
90
protected ServerSocket getPipeServerSocket() {
91
return binder.getPipeServerSocket();
92
}
93
94
/** Return <code>DebugeeArgumentHandler</code> of the debugee object. */
95
public DebugeeArgumentHandler getArgumentHandler() {
96
return binder.getArgumentHandler();
97
}
98
99
/** Return <code>Log</code> of the debugee object. */
100
public Log getLog() {
101
return log;
102
}
103
104
/** Return <code>Process</code> object associated with debugee VM or <i>null</i>. */
105
public Process getProcess() {
106
return process;
107
}
108
109
// --------------------------------------------------- //
110
111
/** Created and return new IOPipe channel to the debugee VM. */
112
public IOPipe createIOPipe() {
113
if (pipe != null) {
114
throw new TestBug("IOPipe channel is already created");
115
}
116
pipe = new IOPipe(this);
117
return pipe;
118
}
119
120
/** Return IOPipe channel or null if not yet ctreated. */
121
public IOPipe getIOPipe() {
122
return pipe;
123
}
124
125
/** Receive and return signal from the debugee VM via IOPipe channel.
126
*
127
* @throws TestBug if IOPipe channel is not created
128
*/
129
public String receiveSignal() {
130
if ( pipe == null )
131
throw new TestBug("IOPipe channel is not initialized");
132
return pipe.readln();
133
}
134
135
/** Receive an expected <code>signal</code> from the debugee VM via IOPipe channel.
136
*
137
* @throws Failure if received signal is not equal to the expected one
138
* @throws TestBug if IOPipe channel is not created
139
*/
140
public void receiveExpectedSignal(String signal) {
141
String line = receiveSignal();
142
if (line == null || !line.equals(signal))
143
throw new Failure("Received unexpected signal from debugee: " + line);
144
display("Received expected signal from debugee: " + signal);
145
}
146
147
/** Send <code>signal</code> to the debugee VM via IOPipe channel.
148
*
149
* @throws TestBug if IOPipe channel is not defined created.
150
*/
151
public void sendSignal(String signal) {
152
if (pipe == null)
153
throw new TestBug("IOPipe channel is not initialized");
154
pipe.println(signal);
155
}
156
157
158
// --------------------------------------------------- //
159
160
/** Wait until the debugee VM shutdown or crash. */
161
abstract protected int waitForDebugee () throws InterruptedException;
162
163
/** Kill the debugee VM. */
164
abstract protected void killDebugee ();
165
166
/** Check whether the debugee VM has been terminated. */
167
abstract public boolean terminated ();
168
169
/** Return the debugee VM exit status. */
170
abstract public int getStatus ();
171
172
/** Get a pipe to write to the debugee's stdin stream. */
173
abstract protected OutputStream getInPipe ();
174
175
/** Get a pipe to read the debugee's stdout stream. */
176
abstract protected InputStream getOutPipe ();
177
178
/** Get a pipe to read the debugee's stderr stream. */
179
abstract protected InputStream getErrPipe ();
180
181
// --------------------------------------------------- //
182
183
/**
184
* Wait until the debugee VM shutdown or crash,
185
* and let finish its stdout, stderr, and stdin
186
* redirectors (if any).
187
*
188
* @return Debugee process exit code.
189
* @see #waitForRedirectors(long)
190
*/
191
public int waitFor () {
192
long timeout = binder.getArgumentHandler().getWaitTime() * 60 * 1000;
193
int exitCode = 0;
194
try {
195
exitCode = waitForDebugee();
196
} catch (InterruptedException ie) {
197
ie.printStackTrace(log.getOutStream());
198
throw new Failure("Caught exception while waiting for debuggee process: \n\t" + ie);
199
}
200
waitForRedirectors(timeout);
201
if (process != null) {
202
process.destroy();
203
}
204
return exitCode;
205
}
206
207
/**
208
* Wait until the debugee VM redirectors to complete for specified <code>timeout</code>.
209
*
210
* @see #waitFor()
211
*/
212
public void waitForRedirectors (long timeout) {
213
try {
214
if (stdinRedirector != null) {
215
if (stdinRedirector.isAlive()) {
216
stdinRedirector.join(timeout);
217
if (stdinRedirector.isAlive()) {
218
log.complain("Timeout for waiting STDIN redirector exceeded");
219
stdinRedirector.interrupt();
220
}
221
}
222
stdinRedirector = null;
223
};
224
if (stdoutRedirector != null) {
225
if (stdoutRedirector.isAlive()) {
226
stdoutRedirector.join(timeout);
227
if (stdoutRedirector.isAlive()) {
228
log.complain("Timeout for waiting STDOUT redirector exceeded");
229
stdoutRedirector.interrupt();
230
}
231
}
232
stdoutRedirector = null;
233
};
234
if (stderrRedirector != null) {
235
if (stderrRedirector.isAlive()) {
236
stderrRedirector.join(timeout);
237
if (stderrRedirector.isAlive()) {
238
log.complain("Timeout for waiting STDERR redirector exceeded");
239
stderrRedirector.interrupt();
240
}
241
}
242
stderrRedirector = null;
243
};
244
} catch (InterruptedException ie) {
245
ie.printStackTrace(log.getOutStream());
246
throw new Failure("Caught exception while waiting for debuggee output redirectors: \n\t"
247
+ ie);
248
}
249
}
250
251
// --------------------------------------------------- //
252
253
/**
254
* Get a pipe to write to the debugee's stdin stream,
255
* or throw TestBug exception is redirected.
256
*/
257
final public OutputStream getStdin () {
258
if (stdinRedirector != null)
259
throw new TestBug("Debugee's stdin is redirected");
260
return getInPipe();
261
}
262
263
/**
264
* Get a pipe to read the debugee's stdout stream,
265
* or throw TestBug exception is redirected.
266
*/
267
final public InputStream getStdout () {
268
if (stdoutRedirector != null)
269
throw new TestBug("Debugee's stdout is redirected");
270
return getOutPipe();
271
}
272
273
/**
274
* Get a pipe to read the debugee's stderr stream,
275
* or throw TestBug exception is redirected.
276
*/
277
final public InputStream getStderr () {
278
if (stderrRedirector != null)
279
throw new TestBug("Debugee's stderr is redirected");
280
return getErrPipe();
281
}
282
283
// --------------------------------------------------- //
284
285
private IORedirector stdoutRedirector = null;
286
private IORedirector stderrRedirector = null;
287
private IORedirector stdinRedirector = null;
288
289
// /**
290
// * Start a thread redirecting the given <code>in</code> stream
291
// * to the debugee's stdin. If the debugee's stdin was already
292
// * redirected, the TestBug exception is thrown.
293
// */
294
// final public void redirectStdin(InputStream in) {
295
// if (stdinRedirector != null)
296
// throw new TestBug("the debugee's stdin is already redirected");
297
// stdinRedirector = new IORedirector(in,getInPipe());
298
// stdinRedirector.setName("IORedirector for stdin");
299
// stdinRedirector.setDaemon(true);
300
// stdinRedirector.start();
301
// }
302
303
/**
304
* Start thread redirecting the debugee's stdout to the
305
* given <code>out</code> stream. If the debugee's stdout
306
* was already redirected, the TestBug exception is thrown.
307
*
308
* @deprecated Use redirectStdout(Log, String) instead.
309
*/
310
@Deprecated
311
public void redirectStdout(OutputStream out) {
312
if (stdoutRedirector != null) {
313
return;
314
}
315
// throw new TestBug("Debugee's stdout is already redirected");
316
stdoutRedirector = new IORedirector(getOutPipe(),out);
317
stdoutRedirector.setPrefix(DEBUGEE_STDOUT_LOG_PREFIX);
318
stdoutRedirector.setName("IORedirector for stdout");
319
stdoutRedirector.setDaemon(true);
320
stdoutRedirector.start();
321
}
322
323
/**
324
* Start thread redirecting the debugee's stdout to the
325
* given <code>Log</code>. If the debugee's stdout
326
* was already redirected, the TestBug exception is thrown.
327
*/
328
public void redirectStdout(Log log, String prefix) {
329
if (stdoutRedirector != null) {
330
// stdoutRedirector.setPrefix(prefix);
331
return;
332
// throw new TestBug("the debugee's stdout is already redirected");
333
}
334
stdoutRedirector = new IORedirector(new BufferedReader(new InputStreamReader(getOutPipe())), log, prefix);
335
stdoutRedirector.setName("IORedirector for stdout");
336
stdoutRedirector.setDaemon(true);
337
stdoutRedirector.start();
338
}
339
340
/**
341
* Start thread redirecting the debugee's stderr to the
342
* given <code>err</code> stream. If the debugee's stderr
343
* was already redirected, the TestBug exception is thrown.
344
*
345
* @deprecated Use redirectStderr(Log, String) instead.
346
*/
347
@Deprecated
348
public void redirectStderr(OutputStream err) {
349
if (stderrRedirector != null) {
350
return;
351
}
352
// throw new TestBug("Debugee's stderr is already redirected");
353
stderrRedirector = new IORedirector(getErrPipe(),err);
354
stderrRedirector.setPrefix(DEBUGEE_STDERR_LOG_PREFIX);
355
stdoutRedirector.setName("IORedirector for stderr");
356
stderrRedirector.setDaemon(true);
357
stderrRedirector.start();
358
}
359
360
/**
361
* Start thread redirecting the debugee's stderr to the
362
* given <code>Log</code>. If the debugee's stderr
363
* was already redirected, the TestBug exception is thrown.
364
*/
365
public void redirectStderr(Log log, String prefix) {
366
if (stderrRedirector != null) {
367
// stderrRedirector.setPrefix(prefix);
368
return;
369
// throw new TestBug("Debugee's stderr is already redirected");
370
}
371
stderrRedirector = new IORedirector(new BufferedReader(new InputStreamReader(getErrPipe())), log, prefix);
372
stdoutRedirector.setName("IORedirector for stderr");
373
stderrRedirector.setDaemon(true);
374
stderrRedirector.start();
375
}
376
377
/**
378
* Start thread redirecting the debugee's stdout/stderr to the
379
* given <code>Log</code> using standard prefixes.
380
* If the debugee's stdout/stderr were already redirected,
381
* the TestBug exception is thrown.
382
*/
383
public void redirectOutput(Log log) {
384
redirectStdout(log, "debugee.stdout> ");
385
redirectStderr(log, "debugee.stderr> ");
386
}
387
// --------------------------------------------------- //
388
389
/**
390
* Kill the debugee VM if it is not terminated yet.
391
*
392
* @throws Throwable if any throwable exception is thrown during finalization
393
*/
394
public void close() {
395
if (checkTermination) {
396
if (!terminated()) {
397
complain("Debugee VM has not exited correctly: trying to kill it");
398
killDebugee();
399
}
400
checkTermination = false;
401
}
402
}
403
404
// --------------------------------------------------- //
405
406
/**
407
* Display log message with prefix.
408
*/
409
protected void display(String message) {
410
log.display(prefix + message);
411
}
412
413
/**
414
* Complain about error with specified message.
415
*/
416
protected void complain(String message) {
417
log.complain(prefix + message);
418
}
419
420
/**
421
* Finalize debuggee VM wrapper by invoking <code>close()</code>.
422
*
423
* @throws Throwable if any throwable exception is thrown during finalization
424
*/
425
protected void finalize() throws Throwable {
426
close();
427
super.finalize();
428
}
429
}
430
431