Java – Running a subprocess works locally but fails with "broken pipe" when ran on Heroku?

huangapple go评论68阅读模式
英文:

Java - Running a subprocess works locally but fails with "broken pipe" when ran on Heroku?

问题

正如背景所述,我有一个基于Java的Discord机器人,在Heroku上部署,使用一个免费的worker dyno。我需要运行一个.exe文件(stockfish 12可执行文件),将输入传递给它并处理输出。我正在使用Java RunTime来创建这个进程,但是当我尝试使用flush()方法向其发送输入时,会抛出"broken pipe"错误。我猜想Heroku可能会在某种程度上关闭输入/输出流,因为此代码在本地运行正常。Heroku是否对创建子进程有限制?

EDIT:我尝试通过硬编码单个命令来简化程序,但仍无法在writer.flush()行之后执行。没有任何输出被打印。

Process process = new ProcessBuilder().command("bin/stockfish_20090216_x64_bmi2.exe").start();

StringBuilder output = new StringBuilder();
BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
writer.write("position fen rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" + "\n");
writer.write("go movetime 1000");
writer.flush();

String line;
while ((line = input.readLine()) != null) {
    output.append(line + "\n");
}

int exitVal = process.waitFor();
if (exitVal == 0) {
    System.out.println("success");
    System.out.println(output.toString());
} else {
    System.out.println("error");
}
英文:

Just as a background, I have a Java-based Discord bot deployed on Heroku using the 1 free worker dyno. I need to run a .exe file (stockfish 12 executable), pass input into it and process output from it. I'm using Java RunTime to create this Process but when I try to send input to it with the flush() method the broken pipe error is thrown. I assume Heroku must be closing the input / output stream somehow because this code runs fine locally. Does Heroku have a limit on creating sub processes?

app[worker.1]: chess.player.ai.stockfish.exception.StockfishEngineException: java.io.IOException: Broken pipe
app[worker.1]: at chess.player.ai.stockfish.engine.UCIEngine.sendCommand(UCIEngine.java:39)
app[worker.1]: at chess.player.ai.stockfish.engine.UCIEngine.passOption(UCIEngine.java:77)
app[worker.1]: at chess.player.ai.stockfish.engine.UCIEngine.<init>(UCIEngine.java:23)
app[worker.1]: at chess.player.ai.stockfish.engine.Stockfish.<init>(Stockfish.java:13)
app[worker.1]: at chess.player.ai.stockfish.StockFishClient.<init>(StockFishClient.java:21)
app[worker.1]: at chess.player.ai.stockfish.StockFishClient$Builder.build(StockFishClient.java:80)

EDIT: I tried to simplify the program by hard coding a single command and it still fails to get past the writer.flush() line. Nothing is printed.

Process process = new ProcessBuilder().command(&quot;bin/stockfish_20090216_x64_bmi2.exe&quot;).start();

StringBuilder output = new StringBuilder();
BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
writer.write(&quot;position fen rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1&quot; + &quot;\n&quot;);
writer.write(&quot;go movetime 1000&quot;);
writer.flush();

String line;
while ((line = input.readLine()) != null) {
    output.append(line + &quot;\n&quot;);
}

int exitVal = process.waitFor();
if (exitVal == 0) {
    System.out.println(&quot;success&quot;);
    System.out.println(output.toString());
}
else {
    System.out.println(&quot;error&quot;);
}

答案1

得分: 0

output流会自行关闭。当您运行一个命令、创建一个新进程或者此命令必须阻塞流并等待输入时,请使用ProcessBuilder,它更易于配置:

new ProcessBuilder().command("cmd.exe", "/c", "command")
                    .directory(new File(path))
                    .redirectInput(new File(path, "input.txt"))
                    .redirectOutput(new File(path, "output.txt"))
                    .redirectError(new File(path, "runtime_error.txt"))
                    .start()
                    .waitFor();
英文:

output stream closes itself. When you run a command, create a new process or this command must block a stream and await an input.

Recommend ProcessBuilder, it is more easily to configure:

new ProcessBuilder().command(&quot;cmd.exe&quot;, &quot;/c&quot;, &quot;command&quot;)
                    .directory(new File(path))
                    .redirectInput(new File(path, &quot;input.txt&quot;))
                    .redirectOutput(new File(path, &quot;output.txt&quot;))
                    .redirectError(new File(path, &quot;runtime_error.txt&quot;))
                    .start()
                    .waitFor();

答案2

得分: 0

原来我使用的是错误的二进制文件。Stockfish 二进制文件有许多不同的格式,显然在我的本地运行的那个在 Heroku 上不起作用。

英文:

Turns out I was using the wrong binary file. Stockfish binary comes in many different formats and apparently the one that works for my local didn't work on Heroku.

huangapple
  • 本文由 发表于 2020年10月8日 09:32:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/64254566.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定