Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 27 additions & 24 deletions src/main/java/org/perlonjava/runtime/operators/SystemOperator.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
Expand Down Expand Up @@ -465,55 +464,59 @@ private static void closeQuietly(BufferedReader reader) {
}

/**
* Writes a line to the current Perl-level STDOUT handle.
* Writes bytes to the current Perl-level STDERR handle.
* This ensures output goes through any Perl-level redirections (e.g.,
* when STDOUT has been reopened to a file via open STDOUT, ">", $file).
* when STDERR has been reopened to a file via open STDERR, ">", $file).
*/
private static void writeToPerlStdout(String line) {
private static void writeToPerlStderrBytes(byte[] buffer, int bytesRead) {
try {
RuntimeIO perlStdout = GlobalVariable.getGlobalIO("main::STDOUT").getRuntimeIO();
if (perlStdout != null) {
perlStdout.write(line + "\n");
RuntimeIO perlStderr = GlobalVariable.getGlobalIO("main::STDERR").getRuntimeIO();
String text = new String(buffer, 0, bytesRead, java.nio.charset.StandardCharsets.ISO_8859_1);
if (perlStderr != null) {
perlStderr.write(text);
} else {
System.out.println(line);
System.err.write(buffer, 0, bytesRead);
}
} catch (Exception e) {
System.out.println(line);
System.err.write(buffer, 0, bytesRead);
}
}

/**
* Writes a line to the current Perl-level STDERR handle.
* Writes bytes to the current Perl-level STDOUT handle.
* This ensures output goes through any Perl-level redirections (e.g.,
* when STDERR has been reopened to a file via open STDERR, ">", $file).
* when STDOUT has been reopened to a file via open STDOUT, ">", $file).
*/
private static void writeToPerlStderr(String line) {
private static void writeToPerlStdoutBytes(byte[] buffer, int bytesRead) {
try {
RuntimeIO perlStderr = GlobalVariable.getGlobalIO("main::STDERR").getRuntimeIO();
if (perlStderr != null) {
perlStderr.write(line + "\n");
RuntimeIO perlStdout = GlobalVariable.getGlobalIO("main::STDOUT").getRuntimeIO();
String text = new String(buffer, 0, bytesRead, java.nio.charset.StandardCharsets.ISO_8859_1);
if (perlStdout != null) {
perlStdout.write(text);
} else {
System.err.println(line);
System.out.write(buffer, 0, bytesRead);
}
} catch (Exception e) {
System.err.println(line);
System.out.write(buffer, 0, bytesRead);
}
}

/**
* Creates a daemon thread that reads from the given input stream and writes
* each line to the current Perl-level handle for the given global name.
* Creates a thread that routes an InputStream to the current Perl-level handle.
* Bytes are written directly without line-by-line processing to preserve
* exact output including or excluding trailing newlines.
* This is used for routing child process stderr/stdout through Perl handles.
*/
private static Thread createStreamRouterThread(InputStream stream, boolean isStderr) {
Thread t = new Thread(() -> {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
String line;
while ((line = reader.readLine()) != null) {
try {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = stream.read(buffer)) != -1) {
if (isStderr) {
writeToPerlStderr(line);
writeToPerlStderrBytes(buffer, bytesRead);
} else {
writeToPerlStdout(line);
writeToPerlStdoutBytes(buffer, bytesRead);
}
}
} catch (IOException e) {
Expand Down
Loading