Skip to content

Commit 078671a

Browse files
committed
Cleanup InputReadJob related ProcessConsole code
- Made console stream fields final for ProcessConsole and InputReadJob - closeStreams() should first set fStreamsClosed to true before closing the stream, to give the InputReadJob a chance to exist without error - InputReadJob should consider that stream could be closed via canceling() - don't log IO errors from InputReadJob if we know that stream is closed Fixes #1033
1 parent bf3898b commit 078671a

1 file changed

Lines changed: 54 additions & 49 deletions

File tree

debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/console/ProcessConsole.java

Lines changed: 54 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -127,15 +127,15 @@ public class ProcessConsole extends IOConsole implements IConsole, IDebugEventSe
127127
* The input stream which can supply user input in console to the system process
128128
* stdin.
129129
*/
130-
private IOConsoleInputStream fUserInput;
130+
private final IOConsoleInputStream fUserInput;
131131
/**
132132
* The stream connected to the system processe's stdin. May be the
133133
* <i>fUserInput</i> stream to supply user input or a FileInputStream to supply
134134
* input from a file.
135135
*/
136-
private volatile InputStream fInput;
136+
private final InputStream fInput;
137137

138-
private FileOutputStream fFileOutputStream;
138+
private final FileOutputStream fFileOutputStream;
139139

140140
private boolean fAllocateConsole;
141141
private String fStdInFile;
@@ -200,6 +200,7 @@ public ProcessConsole(IProcess process, IConsoleColorProvider colorProvider, Str
200200
}
201201
}
202202

203+
FileOutputStream outputStream = null;
203204
if (file != null && configuration != null) {
204205
IWorkspace workspace = ResourcesPlugin.getWorkspace();
205206
IWorkspaceRoot root = workspace.getRoot();
@@ -221,7 +222,7 @@ public ProcessConsole(IProcess process, IConsoleColorProvider colorProvider, Str
221222
}
222223

223224
File outputFile = new File(file);
224-
fFileOutputStream = new FileOutputStream(outputFile, append);
225+
outputStream = new FileOutputStream(outputFile, append);
225226
fileLoc = outputFile.getAbsolutePath();
226227

227228
message = MessageFormat.format(ConsoleMessages.ProcessConsole_1, fileLoc);
@@ -243,12 +244,14 @@ public ProcessConsole(IProcess process, IConsoleColorProvider colorProvider, Str
243244
} catch (CoreException e) {
244245
}
245246
}
247+
fFileOutputStream = outputStream;
248+
InputStream inputStream = null;
246249
if (fStdInFile != null && configuration != null) {
247250
String message = null;
248251
try {
249-
fInput = new FileInputStream(new File(fStdInFile));
250-
if (fInput != null) {
251-
setInputStream(fInput);
252+
inputStream = new FileInputStream(new File(fStdInFile));
253+
if (inputStream != null) {
254+
setInputStream(inputStream);
252255
}
253256

254257
} catch (FileNotFoundException e) {
@@ -263,9 +266,10 @@ public ProcessConsole(IProcess process, IConsoleColorProvider colorProvider, Str
263266
}
264267
}
265268
fColorProvider = colorProvider;
266-
if (fInput == null) {
267-
fInput = getInputStream();
269+
if (inputStream == null) {
270+
inputStream = getInputStream();
268271
}
272+
fInput = inputStream;
269273

270274
colorProvider.connect(fProcess, this);
271275

@@ -560,8 +564,8 @@ public void propertyChange(PropertyChangeEvent evt) {
560564
stream.setColor(fColorProvider.getColor(IDebugUIConstants.ID_STANDARD_ERROR_STREAM));
561565
}
562566
} else if (property.equals(IDebugPreferenceConstants.CONSOLE_SYS_IN_COLOR)) {
563-
if (fInput != null && fInput instanceof IOConsoleInputStream) {
564-
((IOConsoleInputStream) fInput).setColor(fColorProvider.getColor(IDebugUIConstants.ID_STANDARD_INPUT_STREAM));
567+
if (fInput instanceof IOConsoleInputStream inputStream) {
568+
inputStream.setColor(fColorProvider.getColor(IDebugUIConstants.ID_STANDARD_INPUT_STREAM));
565569
}
566570
} else if (property.equals(IDebugUIConstants.PREF_CONSOLE_FONT)) {
567571
setFont(JFaceResources.getFont(IDebugUIConstants.PREF_CONSOLE_FONT));
@@ -616,29 +620,32 @@ private synchronized void closeStreams() {
616620
if (fStreamsClosed) {
617621
return;
618622
}
619-
for (StreamListener listener : fStreamListeners) {
620-
listener.closeStream();
621-
}
622-
if (fFileOutputStream != null) {
623-
synchronized (fFileOutputStream) {
624-
try {
625-
fFileOutputStream.flush();
626-
fFileOutputStream.close();
627-
} catch (IOException e) {
623+
fStreamsClosed = true;
624+
try {
625+
for (StreamListener listener : fStreamListeners) {
626+
listener.closeStream();
627+
}
628+
} finally {
629+
if (fFileOutputStream != null) {
630+
synchronized (fFileOutputStream) {
631+
try {
632+
fFileOutputStream.flush();
633+
fFileOutputStream.close();
634+
} catch (IOException e) {
635+
}
628636
}
629637
}
630-
}
631-
try {
632-
fInput.close();
633-
} catch (IOException e) {
634-
}
635-
if (fInput != fUserInput) {
636638
try {
637-
fUserInput.close();
639+
fInput.close();
638640
} catch (IOException e) {
639641
}
642+
if (fInput != fUserInput) {
643+
try {
644+
fUserInput.close();
645+
} catch (IOException e) {
646+
}
647+
}
640648
}
641-
fStreamsClosed = true;
642649
}
643650

644651
/**
@@ -649,9 +656,6 @@ private synchronized void disposeStreams() {
649656
for (StreamListener listener : fStreamListeners) {
650657
listener.dispose();
651658
}
652-
fFileOutputStream = null;
653-
fInput = null;
654-
fUserInput = null;
655659
}
656660

657661
@Override
@@ -961,17 +965,24 @@ private class InputReadJob extends Job {
961965
* The {@link InputStream} this job is currently reading from or maybe blocking
962966
* on. May be <code>null</code>.
963967
*/
964-
private InputStream readingStream;
968+
private final InputStream readingStream;
969+
private volatile boolean streamClosed;
965970

966971
InputReadJob(IStreamsProxy streamsProxy) {
967972
super("Process Console Input Job"); //$NON-NLS-1$
968973
this.streamsProxy = streamsProxy;
974+
readingStream = fInput;
975+
}
976+
977+
private boolean isStreamClosed() {
978+
return fStreamsClosed || streamClosed;
969979
}
970980

971981
@Override
972982
protected void canceling() {
973983
super.canceling();
974984
if (readingStream != null) {
985+
streamClosed = true;
975986
// Close stream or job may not be able to cancel.
976987
// This is primary for IOConsoleInputStream because there is no guarantee an
977988
// arbitrary InputStream will release a blocked read() on close.
@@ -990,49 +1001,42 @@ public boolean belongsTo(Object family) {
9901001

9911002
@Override
9921003
protected IStatus run(IProgressMonitor monitor) {
993-
if (fInput == null || fStreamsClosed) {
1004+
if (readingStream == null || isStreamClosed()) {
9941005
return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS;
9951006
}
996-
if (streamsProxy instanceof IBinaryStreamsProxy) {
1007+
if (streamsProxy instanceof IBinaryStreamsProxy proxy) {
9971008
// Pass data without processing. The preferred variant. There is no need for
9981009
// this job to know about encodings.
9991010
try {
10001011
byte[] buffer = new byte[1024];
10011012
int bytesRead = 0;
10021013
while (bytesRead >= 0 && !monitor.isCanceled()) {
1003-
if (fInput == null || fStreamsClosed) {
1014+
if (isStreamClosed()) {
10041015
break;
10051016
}
1006-
if (fInput != readingStream) {
1007-
readingStream = fInput;
1008-
}
10091017
bytesRead = readingStream.read(buffer);
10101018
if (bytesRead > 0) {
1011-
((IBinaryStreamsProxy) streamsProxy).write(buffer, 0, bytesRead);
1019+
proxy.write(buffer, 0, bytesRead);
10121020
}
10131021
}
10141022
} catch (IOException e) {
1015-
DebugUIPlugin.log(e);
1023+
if (!isStreamClosed()) {
1024+
DebugUIPlugin.log(e);
1025+
}
10161026
}
10171027
} else {
10181028
// Decode data to strings. The legacy variant used if the proxy does not
10191029
// implement the binary API.
10201030
Charset encoding = getCharset();
1021-
readingStream = fInput;
10221031
InputStreamReader streamReader = (encoding == null ? new InputStreamReader(readingStream)
10231032
: new InputStreamReader(readingStream, encoding));
10241033
try {
10251034
char[] cbuf = new char[1024];
10261035
int charRead = 0;
10271036
while (charRead >= 0 && !monitor.isCanceled()) {
1028-
if (fInput == null || fStreamsClosed) {
1037+
if (isStreamClosed()) {
10291038
break;
10301039
}
1031-
if (fInput != readingStream) {
1032-
readingStream = fInput;
1033-
streamReader = (encoding == null ? new InputStreamReader(readingStream)
1034-
: new InputStreamReader(readingStream, encoding));
1035-
}
10361040

10371041
charRead = streamReader.read(cbuf);
10381042
if (charRead > 0) {
@@ -1041,10 +1045,11 @@ protected IStatus run(IProgressMonitor monitor) {
10411045
}
10421046
}
10431047
} catch (IOException e) {
1044-
DebugUIPlugin.log(e);
1048+
if (!isStreamClosed()) {
1049+
DebugUIPlugin.log(e);
1050+
}
10451051
}
10461052
}
1047-
readingStream = null;
10481053
return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS;
10491054
}
10501055
}

0 commit comments

Comments
 (0)