Skip to content

Commit 70962eb

Browse files
committed
simplify and fix os.system
1 parent cced088 commit 70962eb

File tree

1 file changed

+45
-27
lines changed

1 file changed

+45
-27
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,11 @@
3232
import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError;
3333
import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError;
3434

35-
import java.io.BufferedReader;
3635
import java.io.Console;
3736
import java.io.IOException;
3837
import java.io.InputStream;
39-
import java.io.InputStreamReader;
4038
import java.io.OutputStream;
39+
import java.lang.ProcessBuilder.Redirect;
4140
import java.math.BigInteger;
4241
import java.nio.ByteBuffer;
4342
import java.nio.channels.NonWritableChannelException;
@@ -88,6 +87,7 @@
8887
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
8988
import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes;
9089
import com.oracle.graal.python.nodes.util.CastToIndexNode;
90+
import com.oracle.graal.python.runtime.PythonContext;
9191
import com.oracle.graal.python.runtime.PythonCore;
9292
import com.oracle.graal.python.runtime.exception.PException;
9393
import com.oracle.graal.python.runtime.exception.PythonErrorType;
@@ -96,6 +96,7 @@
9696
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
9797
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
9898
import com.oracle.truffle.api.TruffleFile;
99+
import com.oracle.truffle.api.TruffleLanguage.Env;
99100
import com.oracle.truffle.api.dsl.Cached;
100101
import com.oracle.truffle.api.dsl.Fallback;
101102
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
@@ -1043,48 +1044,65 @@ abstract static class SystemNode extends PythonBuiltinNode {
10431044
static final String[] shell = System.getProperty("os.name").toLowerCase().startsWith("windows") ? new String[]{"cmd.exe", "/c"}
10441045
: new String[]{(System.getenv().getOrDefault("SHELL", "sh")), "-c"};
10451046

1046-
class StreamGobbler extends Thread {
1047-
static final int bufsize = 4096;
1048-
InputStream is;
1049-
OutputStream type;
1050-
private char[] buf;
1051-
1052-
StreamGobbler(InputStream is, OutputStream outputStream) {
1053-
this.is = is;
1054-
this.type = outputStream;
1055-
this.buf = new char[bufsize];
1047+
static class PipePump extends Thread {
1048+
private final InputStream in;
1049+
private final OutputStream out;
1050+
private final byte[] buffer;
1051+
private boolean finish;
1052+
1053+
public PipePump(InputStream in, OutputStream out) {
1054+
this.in = in;
1055+
this.out = out;
1056+
this.buffer = new byte[8192];
1057+
this.finish = false;
10561058
}
10571059

10581060
@Override
1059-
@TruffleBoundary
10601061
public void run() {
10611062
try {
1062-
InputStreamReader isr = new InputStreamReader(is);
1063-
BufferedReader br = new BufferedReader(isr);
1064-
int readSz = 0;
1065-
while ((readSz = br.read(buf, 0, bufsize)) > 0) {
1066-
type.write(new String(buf).getBytes(), 0, readSz);
1063+
while (!Thread.interrupted() && !finish) {
1064+
int read = in.read(buffer, 0, in.available());
1065+
if (read == -1) {
1066+
return;
1067+
}
1068+
out.write(buffer, 0, read);
10671069
}
1068-
} catch (IOException ioe) {
1070+
} catch (IOException e) {
10691071
}
10701072
}
1073+
1074+
public void finish() {
1075+
Thread.yield();
1076+
finish = true;
1077+
}
10711078
}
10721079

10731080
@TruffleBoundary
10741081
@Specialization
10751082
int system(String cmd) {
1076-
if (!getContext().isExecutableAccessAllowed()) {
1083+
PythonContext context = getContext();
1084+
if (!context.isExecutableAccessAllowed()) {
10771085
return -1;
10781086
}
10791087
String[] command = new String[]{shell[0], shell[1], cmd};
1088+
Env env = context.getEnv();
10801089
try {
1081-
Runtime rt = Runtime.getRuntime();
1082-
Process proc = rt.exec(command);
1083-
StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), getContext().getStandardErr());
1084-
StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), getContext().getStandardOut());
1085-
errorGobbler.start();
1086-
outputGobbler.start();
1087-
return proc.waitFor();
1090+
ProcessBuilder pb = new ProcessBuilder(command);
1091+
pb.redirectInput(Redirect.PIPE);
1092+
pb.redirectOutput(Redirect.PIPE);
1093+
pb.redirectError(Redirect.PIPE);
1094+
Process proc = pb.start();
1095+
PipePump stdin = new PipePump(env.in(), proc.getOutputStream());
1096+
PipePump stdout = new PipePump(proc.getInputStream(), env.out());
1097+
PipePump stderr = new PipePump(proc.getErrorStream(), env.err());
1098+
stdin.start();
1099+
stdout.start();
1100+
stderr.start();
1101+
int exitStatus = proc.waitFor();
1102+
stdin.finish();
1103+
stdout.finish();
1104+
stderr.finish();
1105+
return exitStatus;
10881106
} catch (IOException | InterruptedException e) {
10891107
return -1;
10901108
}

0 commit comments

Comments
 (0)