Skip to content

Commit

Permalink
don't fail if subprocess finished (#166)
Browse files Browse the repository at this point in the history
e.g. the user exited `less` before all results were written...

example from joern _before_ this PR:
```
importCpg("/home/mp/tmp/cpgtesting/linux-kernel/linux6-drivers-scsi.fg")
cpg.method.name.browse
Exception in thread "less stdin thread" java.io.IOException: Broken pipe
        at java.base/java.io.FileOutputStream.writeBytes(Native Method)
        at java.base/java.io.FileOutputStream.write(FileOutputStream.java:349)
        at java.base/java.io.BufferedOutputStream.write(BufferedOutputStream.java:123)
        at java.base/sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:234)
        at java.base/sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:304)
        at java.base/sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:282)
        at java.base/sun.nio.cs.StreamEncoder.write(StreamEncoder.java:132)
        at java.base/java.io.OutputStreamWriter.write(OutputStreamWriter.java:205)
        at java.base/java.io.BufferedWriter.flushBuffer(BufferedWriter.java:120)
        at java.base/java.io.BufferedWriter.write(BufferedWriter.java:233)
        at replpp.Operators$$anon$1.processInput$$anonfun$1(Operators.scala:140)
        at java.base/java.lang.Thread.run(Thread.java:840)
```

This PR silences this issue.
  • Loading branch information
mpollmeier authored Jul 23, 2024
1 parent db1b24b commit 9ba08d9
Showing 1 changed file with 24 additions and 8 deletions.
32 changes: 24 additions & 8 deletions core/src/main/scala/replpp/Operators.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import java.nio.charset.StandardCharsets
import java.nio.file.{Path, Paths}
import scala.jdk.CollectionConverters.*
import scala.util.{Try, Using}
import scala.util.control.NonFatal

/**
* Operators to redirect output to files or pipe them into external commands / processes,
Expand All @@ -22,6 +23,13 @@ import scala.util.{Try, Using}
* */
object Operators {

def main(args: Array[String]): Unit = {
given Colors = Colors.BlackWhite
val value = "foo"
val result = value #| "cat"
println(result)
}

/** output from an external command, e.g. when using `#|` */
case class ProcessResults(stdout: String, stderr: String)

Expand Down Expand Up @@ -135,15 +143,23 @@ object Operators {
val chunkSize = 8192
var remaining = bytes.length
var pos = 0
while (remaining > 0) {
val currentWindow = math.min(remaining, chunkSize)
stdin.buffered.write(value, pos, currentWindow)
pos += currentWindow
remaining -= currentWindow
var stopped = false
Using.resource(stdin) { stdin =>
while (remaining > 0 && !stopped) {
val currentWindow = math.min(remaining, chunkSize)
try {
stdin.buffered.write(value, pos, currentWindow)
pos += currentWindow
remaining -= currentWindow
} catch {
case t: Throwable =>
// most likely the user exited the subprocess
stopped = true
}
}
// flush stdin, but ignore errors
try {stdin.flush()} catch { case NonFatal(_) => /*ignore*/ }
}

stdin.flush()
stdin.close()
}
}
}
Expand Down

0 comments on commit 9ba08d9

Please sign in to comment.