Skip to content

Commit 8a1e6c8

Browse files
author
Federico Fissore
committed
CollectStdOutExecutor and CollectStdOutStdErrExecutor were plain wrong, were losing data and were blocking compilation. Fixes #3124 and #3115
1 parent 5faa1c9 commit 8a1e6c8

File tree

8 files changed

+105
-135
lines changed

8 files changed

+105
-135
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package cc.arduino;
2+
3+
import processing.app.debug.MessageConsumer;
4+
5+
import java.io.BufferedReader;
6+
import java.io.InputStream;
7+
import java.io.InputStreamReader;
8+
9+
/**
10+
* A version of StreamPumper from commons-exec that write to a MessageConsumer
11+
*/
12+
public class MyStreamPumper implements Runnable {
13+
14+
/**
15+
* the input stream to pump from
16+
*/
17+
private final BufferedReader reader;
18+
19+
/**
20+
* the output stream to pmp into
21+
*/
22+
private final MessageConsumer messageConsumer;
23+
24+
/**
25+
* was the end of the stream reached
26+
*/
27+
private boolean finished;
28+
29+
public MyStreamPumper(final InputStream is, final MessageConsumer messageConsumer) {
30+
this.reader = new BufferedReader(new InputStreamReader(is));
31+
this.messageConsumer = messageConsumer;
32+
}
33+
34+
/**
35+
* Copies data from the input stream to the output stream. Terminates as
36+
* soon as the input stream is closed or an error occurs.
37+
*/
38+
public void run() {
39+
synchronized (this) {
40+
// Just in case this object is reused in the future
41+
finished = false;
42+
}
43+
44+
try {
45+
String line;
46+
while ((line = reader.readLine()) != null) {
47+
messageConsumer.message(line + "\n");
48+
}
49+
} catch (Exception e) {
50+
// nothing to do - happens quite often with watchdog
51+
} finally {
52+
synchronized (this) {
53+
finished = true;
54+
notifyAll();
55+
}
56+
}
57+
}
58+
59+
/**
60+
* Tells whether the end of the stream has been reached.
61+
*
62+
* @return true is the stream has been exhausted.
63+
*/
64+
public synchronized boolean isFinished() {
65+
return finished;
66+
}
67+
68+
/**
69+
* This method blocks until the stream pumper finishes.
70+
*
71+
* @see #isFinished()
72+
*/
73+
public synchronized void waitFor() throws InterruptedException {
74+
while (!isFinished()) {
75+
wait();
76+
}
77+
}
78+
}

arduino-core/src/cc/arduino/contributions/packages/ContributionInstaller.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,15 @@
3737
import cc.arduino.utils.Progress;
3838
import com.google.common.collect.Collections2;
3939
import org.apache.commons.exec.CommandLine;
40+
import org.apache.commons.exec.DefaultExecutor;
4041
import org.apache.commons.exec.Executor;
42+
import org.apache.commons.exec.PumpStreamHandler;
4143
import processing.app.BaseNoGui;
4244
import processing.app.I18n;
4345
import processing.app.Platform;
4446
import processing.app.PreferencesData;
4547
import processing.app.helpers.FileUtils;
4648
import processing.app.helpers.filefilters.OnlyDirs;
47-
import processing.app.tools.CollectStdOutStdErrExecutor;
4849

4950
import java.io.ByteArrayOutputStream;
5051
import java.io.File;
@@ -179,7 +180,8 @@ private void executePostInstallScriptIfAny(File folder) throws IOException {
179180

180181
ByteArrayOutputStream stdout = new ByteArrayOutputStream();
181182
ByteArrayOutputStream stderr = new ByteArrayOutputStream();
182-
Executor executor = new CollectStdOutStdErrExecutor(stdout, stderr);
183+
Executor executor = new DefaultExecutor();
184+
executor.setStreamHandler(new PumpStreamHandler(stdout, stderr));
183185
executor.setWorkingDirectory(folder);
184186
executor.setExitValues(null);
185187
int exitValue = executor.execute(new CommandLine(postInstallScript));

arduino-core/src/processing/app/debug/Compiler.java

+7-32
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,13 @@
3535
import java.util.SortedSet;
3636
import java.util.TreeSet;
3737

38+
import cc.arduino.MyStreamPumper;
3839
import cc.arduino.packages.BoardPort;
3940
import cc.arduino.packages.Uploader;
4041
import cc.arduino.packages.UploaderFactory;
4142

4243
import org.apache.commons.compress.utils.IOUtils;
43-
import org.apache.commons.exec.CommandLine;
44-
import org.apache.commons.exec.DefaultExecutor;
45-
import org.apache.commons.exec.ExecuteStreamHandler;
44+
import org.apache.commons.exec.*;
4645
import processing.app.BaseNoGui;
4746
import processing.app.I18n;
4847
import processing.app.PreferencesData;
@@ -703,37 +702,13 @@ private void execAsynchronously(String[] command) throws RunnerException {
703702
}
704703

705704
DefaultExecutor executor = new DefaultExecutor();
706-
executor.setStreamHandler(new ExecuteStreamHandler() {
707-
@Override
708-
public void setProcessInputStream(OutputStream os) throws IOException {
709-
710-
}
711-
712-
@Override
713-
public void setProcessErrorStream(InputStream is) throws IOException {
714-
forwardToMessage(is);
715-
}
716-
717-
@Override
718-
public void setProcessOutputStream(InputStream is) throws IOException {
719-
forwardToMessage(is);
720-
}
721-
722-
private void forwardToMessage(InputStream is) throws IOException {
723-
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
724-
String line;
725-
while ((line = reader.readLine()) != null) {
726-
message(line + "\n");
727-
}
728-
}
729-
730-
@Override
731-
public void start() throws IOException {
732-
733-
}
705+
executor.setStreamHandler(new PumpStreamHandler() {
734706

735707
@Override
736-
public void stop() {
708+
protected Thread createPump(InputStream is, OutputStream os, boolean closeWhenExhausted) {
709+
final Thread result = new Thread(new MyStreamPumper(is, Compiler.this));
710+
result.setDaemon(true);
711+
return result;
737712

738713
}
739714
});

arduino-core/src/processing/app/linux/Platform.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@
2323
package processing.app.linux;
2424

2525
import org.apache.commons.exec.CommandLine;
26+
import org.apache.commons.exec.DefaultExecutor;
2627
import org.apache.commons.exec.Executor;
28+
import org.apache.commons.exec.PumpStreamHandler;
2729
import processing.app.PreferencesData;
2830
import processing.app.debug.TargetPackage;
2931
import processing.app.legacy.PConstants;
30-
import processing.app.tools.CollectStdOutExecutor;
3132

3233
import java.io.ByteArrayOutputStream;
3334
import java.io.File;
@@ -124,7 +125,8 @@ public String getName() {
124125
public Map<String, Object> resolveDeviceAttachedTo(String serial, Map<String, TargetPackage> packages, String devicesListOutput) {
125126
assert packages != null;
126127
ByteArrayOutputStream baos = new ByteArrayOutputStream();
127-
Executor executor = new CollectStdOutExecutor(baos);
128+
Executor executor = new DefaultExecutor();
129+
executor.setStreamHandler(new PumpStreamHandler(baos, null));
128130

129131
try {
130132
CommandLine toDevicePath = CommandLine.parse("udevadm info -q path -n " + serial);

arduino-core/src/processing/app/macosx/Platform.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,13 @@
2525
import cc.arduino.packages.BoardPort;
2626
import com.apple.eio.FileManager;
2727
import org.apache.commons.exec.CommandLine;
28+
import org.apache.commons.exec.DefaultExecutor;
2829
import org.apache.commons.exec.Executor;
30+
import org.apache.commons.exec.PumpStreamHandler;
2931
import org.apache.commons.lang3.StringUtils;
3032
import processing.app.debug.TargetPackage;
3133
import processing.app.legacy.PApplet;
3234
import processing.app.legacy.PConstants;
33-
import processing.app.tools.CollectStdOutExecutor;
3435

3536
import java.awt.*;
3637
import java.io.*;
@@ -67,7 +68,8 @@ public void init() throws IOException {
6768
private void discoverRealOsArch() throws IOException {
6869
CommandLine uname = CommandLine.parse("uname -m");
6970
ByteArrayOutputStream baos = new ByteArrayOutputStream();
70-
CollectStdOutExecutor executor = new CollectStdOutExecutor(baos);
71+
Executor executor = new DefaultExecutor();
72+
executor.setStreamHandler(new PumpStreamHandler(baos, null));
7173
executor.execute(uname);
7274
osArch = StringUtils.trim(new String(baos.toByteArray()));
7375
}
@@ -214,7 +216,8 @@ public Map<String, Object> resolveDeviceAttachedTo(String serial, Map<String, Ta
214216
@Override
215217
public String preListAllCandidateDevices() {
216218
ByteArrayOutputStream baos = new ByteArrayOutputStream();
217-
Executor executor = new CollectStdOutExecutor(baos);
219+
Executor executor = new DefaultExecutor();
220+
executor.setStreamHandler(new PumpStreamHandler(baos, null));
218221

219222
try {
220223
CommandLine toDevicePath = CommandLine.parse("/usr/sbin/system_profiler SPUSBDataType");

arduino-core/src/processing/app/tools/CollectStdOutExecutor.java

-44
This file was deleted.

arduino-core/src/processing/app/tools/CollectStdOutStdErrExecutor.java

-49
This file was deleted.

arduino-core/src/processing/app/windows/Platform.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@
2323
package processing.app.windows;
2424

2525
import org.apache.commons.exec.CommandLine;
26+
import org.apache.commons.exec.DefaultExecutor;
2627
import org.apache.commons.exec.Executor;
28+
import org.apache.commons.exec.PumpStreamHandler;
2729
import processing.app.debug.TargetPackage;
2830
import processing.app.legacy.PApplet;
2931
import processing.app.legacy.PConstants;
30-
import processing.app.tools.CollectStdOutExecutor;
3132

3233
import java.io.ByteArrayOutputStream;
3334
import java.io.File;
@@ -62,7 +63,8 @@ private void recoverDefaultSketchbookFolder() throws IOException {
6263

6364
private String getFolderPathFromRegistry(String folderType) throws IOException {
6465
ByteArrayOutputStream baos = new ByteArrayOutputStream();
65-
Executor executor = new CollectStdOutExecutor(baos);
66+
Executor executor = new DefaultExecutor();
67+
executor.setStreamHandler(new PumpStreamHandler(baos, null));
6668

6769
CommandLine toDevicePath = CommandLine.parse("reg query \"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\" /v \"" + folderType + "\"");
6870
executor.execute(toDevicePath);
@@ -193,7 +195,8 @@ public Map<String, Object> resolveDeviceAttachedTo(String serial, Map<String, Ta
193195
@Override
194196
public String preListAllCandidateDevices() {
195197
ByteArrayOutputStream baos = new ByteArrayOutputStream();
196-
Executor executor = new CollectStdOutExecutor(baos);
198+
Executor executor = new DefaultExecutor();
199+
executor.setStreamHandler(new PumpStreamHandler(baos, null));
197200

198201
try {
199202
String listComPorts = new File(System.getProperty("user.dir"), "hardware/tools/listComPorts.exe").getCanonicalPath();

0 commit comments

Comments
 (0)