@@ -36,13 +36,35 @@ object PosixPluginFrontend extends PluginFrontend {
36
36
37
37
Future {
38
38
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()
42
43
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
+ }
46
68
}
47
69
}
48
70
(sh, InternalState (inputPipe, outputPipe, tempDirPath, sh))
0 commit comments