Skip to content

Commit 392ec31

Browse files
committed
Only start the stream monitoring after events are send out
Currently it is almost impossible to capture the full binary stream of a process even if one adds a listener right after creation of the stream proxy. The reason is that the streams are immediately started to being read in the constructor. The code currently uses some caching in place but this only works reliable for a single listener and is then reset afterwards having other missing data depending on how fast they can register. Even worse there is a small chance that after registration and before reading the buffer some bytes are received and then is processed before the buffer contents. This now creates a new constructor that only creates the stream but do not start them. Instead users must call the method startMonitoring for this. The RuntimeProcess now uses this constructor to delay the start of stream reading unless all notifications are performed so other parties can register accordingly.
1 parent 39d95f8 commit 392ec31

File tree

2 files changed

+62
-11
lines changed

2 files changed

+62
-11
lines changed

debug/org.eclipse.debug.core/core/org/eclipse/debug/core/model/RuntimeProcess.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,22 @@ public RuntimeProcess(ILaunch launch, Process process, String name, Map<String,
166166
launch.addProcess(this);
167167
fMonitor.start();
168168
fireCreationEvent();
169+
startStreams();
170+
}
171+
172+
/**
173+
* Called after notification that this runtime process is created to start
174+
* the reading of streams. Must be overridden if a custom
175+
* {@link IStreamsProxy} instance is provided by
176+
* {@link #createStreamsProxy()} that do not extends {@link StreamsProxy}
177+
* and does not start the stream reading in any other mean.
178+
*
179+
* @since 3.23
180+
*/
181+
protected void startStreams() {
182+
if (fStreamsProxy instanceof StreamsProxy impl) {
183+
impl.startMonitoring(fThreadNameSuffix);
184+
}
169185
}
170186

171187
private static String getPidInfo(Process process, ILaunch launch) {
@@ -389,7 +405,7 @@ protected IStreamsProxy createStreamsProxy() {
389405
if (charset == null) {
390406
charset = Platform.getSystemCharset();
391407
}
392-
return new StreamsProxy(getSystemProcess(), charset, fThreadNameSuffix);
408+
return new StreamsProxy(getSystemProcess(), charset);
393409
}
394410

395411
/**

debug/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/StreamsProxy.java

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616

1717
import java.io.IOException;
18+
import java.io.InputStream;
19+
import java.io.OutputStream;
1820
import java.nio.charset.Charset;
1921

2022
import org.eclipse.debug.core.model.IBinaryStreamMonitor;
@@ -33,43 +35,75 @@ public class StreamsProxy implements IBinaryStreamsProxy {
3335
/**
3436
* The monitor for the output stream (connected to standard out of the process)
3537
*/
36-
private OutputStreamMonitor fOutputMonitor;
38+
private final OutputStreamMonitor fOutputMonitor;
3739
/**
3840
* The monitor for the error stream (connected to standard error of the process)
3941
*/
40-
private OutputStreamMonitor fErrorMonitor;
42+
private final OutputStreamMonitor fErrorMonitor;
4143
/**
4244
* The monitor for the input stream (connected to standard in of the process)
4345
*/
44-
private InputStreamMonitor fInputMonitor;
46+
private final InputStreamMonitor fInputMonitor;
4547
/**
4648
* Records the open/closed state of communications with
4749
* the underlying streams. Note: fClosed is initialized to
4850
* <code>false</code> by default.
4951
*/
5052
private boolean fClosed;
53+
private boolean started;
5154

5255
/**
5356
* Creates a <code>StreamsProxy</code> on the streams of the given system
54-
* process.
57+
* process and starts the monitoring.
5558
*
5659
* @param process system process to create a streams proxy on
5760
* @param charset the process's charset or <code>null</code> if default
5861
* @param suffix Thread name suffix
5962
*/
60-
@SuppressWarnings("resource")
6163
public StreamsProxy(Process process, Charset charset, String suffix) {
64+
this(process, charset);
65+
startMonitoring(suffix);
66+
}
67+
68+
/**
69+
* Creates a <code>StreamsProxy</code> on the streams of the given system
70+
* process, monitoring must be started separately.
71+
*
72+
* @param process system process to create a streams proxy on
73+
* @param charset the process's charset or <code>null</code> if default
74+
*/
75+
@SuppressWarnings("resource")
76+
public StreamsProxy(Process process, Charset charset) {
6277
if (process == null) {
63-
return;
78+
fOutputMonitor = new OutputStreamMonitor(InputStream.nullInputStream(), charset);
79+
fErrorMonitor = new OutputStreamMonitor(InputStream.nullInputStream(), charset);
80+
fInputMonitor = new InputStreamMonitor(OutputStream.nullOutputStream(), charset);
81+
} else {
82+
fOutputMonitor = new OutputStreamMonitor(process.getInputStream(), charset);
83+
fErrorMonitor = new OutputStreamMonitor(process.getErrorStream(), charset);
84+
fInputMonitor = new InputStreamMonitor(process.getOutputStream(), charset);
6485
}
65-
fOutputMonitor = new OutputStreamMonitor(process.getInputStream(), charset);
66-
fErrorMonitor = new OutputStreamMonitor(process.getErrorStream(), charset);
67-
fInputMonitor = new InputStreamMonitor(process.getOutputStream(), charset);
86+
}
87+
88+
/**
89+
* Starts the monitoring of streams using the given suffix
90+
*
91+
* @param suffix
92+
*/
93+
public void startMonitoring(String suffix) {
94+
start();
6895
fOutputMonitor.startMonitoring("Output Stream Monitor" + suffix); //$NON-NLS-1$
6996
fErrorMonitor.startMonitoring("Error Stream Monitor" + suffix); //$NON-NLS-1$
7097
fInputMonitor.startMonitoring("Input Stream Monitor" + suffix); //$NON-NLS-1$
7198
}
7299

100+
private synchronized void start() {
101+
if (started) {
102+
throw new IllegalStateException("Already started!"); //$NON-NLS-1$
103+
}
104+
started = true;
105+
}
106+
73107
/**
74108
* Creates a <code>StreamsProxy</code> on the streams of the given system
75109
* process.
@@ -78,7 +112,7 @@ public StreamsProxy(Process process, Charset charset, String suffix) {
78112
* @param encoding the process's encoding or <code>null</code> if default
79113
* @deprecated use {@link #StreamsProxy(Process, Charset, String)} instead
80114
*/
81-
@Deprecated
115+
@Deprecated(forRemoval = true, since = "2025-06")
82116
public StreamsProxy(Process process, String encoding) {
83117
// This constructor was once removed in favor of the Charset variant
84118
// but Bug 562653 brought up a client which use this internal class via
@@ -178,4 +212,5 @@ public void write(byte[] data, int offset, int length) throws IOException {
178212
throw new IOException();
179213
}
180214
}
215+
181216
}

0 commit comments

Comments
 (0)