Skip to content

Commit 9ba41d9

Browse files
committed
Handle all failures in Future
1 parent 3041aed commit 9ba41d9

File tree

2 files changed

+36
-12
lines changed

2 files changed

+36
-12
lines changed

bridge/src/main/scala/protocbridge/frontend/PluginFrontend.scala

+8-6
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,15 @@ object PluginFrontend {
4747
gen: ProtocCodeGenerator,
4848
request: Array[Byte]
4949
): Array[Byte] = {
50-
Try {
50+
// Use try-catch to handle all Throwable including OutOfMemoryError, StackOverflowError, etc.
51+
try {
5152
gen.run(request)
52-
}.recover { case throwable =>
53-
createCodeGeneratorResponseWithError(
54-
throwable.toString + "\n" + getStackTrace(throwable)
55-
)
56-
}.get
53+
} catch {
54+
case throwable: Throwable =>
55+
createCodeGeneratorResponseWithError(
56+
throwable.toString + "\n" + getStackTrace(throwable)
57+
)
58+
}
5759
}
5860

5961
def createCodeGeneratorResponseWithError(error: String): Array[Byte] = {

bridge/src/main/scala/protocbridge/frontend/PosixPluginFrontend.scala

+28-6
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,35 @@ object PosixPluginFrontend extends PluginFrontend {
3636

3737
Future {
3838
blocking {
39-
val fsin = Files.newInputStream(inputPipe)
40-
val response = PluginFrontend.runWithInputStream(plugin, fsin, env)
41-
fsin.close()
39+
try {
40+
val fsin = Files.newInputStream(inputPipe)
41+
val response = PluginFrontend.runWithInputStream(plugin, fsin, env)
42+
fsin.close()
4243

43-
val fsout = Files.newOutputStream(outputPipe)
44-
fsout.write(response)
45-
fsout.close()
44+
val fsout = Files.newOutputStream(outputPipe)
45+
fsout.write(response)
46+
fsout.close()
47+
} catch {
48+
case e: Throwable =>
49+
// Handles rare exceptions not already gracefully handled in `runWithBytes`.
50+
// Such exceptions aren't converted to `CodeGeneratorResponse`
51+
// because `fsin` might not be fully consumed,
52+
// therefore the plugin shell script might hang on `inputPipe`,
53+
// and never consume `CodeGeneratorResponse`.
54+
System.err.println("Exception occurred in PluginFrontend outside runWithBytes")
55+
e.printStackTrace(System.err)
56+
// Force an exit of the program.
57+
// This is because the plugin shell script might hang on `inputPipe`,
58+
// due to `fsin` not fully consumed.
59+
// Or it might hang on `outputPipe`, due to `fsout` not closed.
60+
// Therefore, the program might be stuck waiting for protoc,
61+
// which in turn is waiting for the plugin shell script.
62+
//
63+
// We can't simply close `fsout` here either,
64+
// because `Files.newOutputStream(outputPipe)` will hang
65+
// if `outputPipe` is not yet opened by the plugin shell script for reading.
66+
sys.exit(1)
67+
}
4668
}
4769
}
4870
(sh, InternalState(inputPipe, outputPipe, tempDirPath, sh))

0 commit comments

Comments
 (0)