Skip to content

Commit 95b14ae

Browse files
committed
[gazelle] Fix 30s hang on javaparser shutdown; avoid GOAWAY noise
The hang happened at shutdown because the server called `System.exit(0)` without replying to the `Lifecycle.Shutdown` RPC. The gRPC server then waited up to 30s with an in-flight call. Closing the client socket immediately would produce a (benign) “Broken pipe” GOAWAY stacktrace. This change results in far faster shutdown of the gRPC server.
1 parent b032e6d commit 95b14ae

File tree

2 files changed

+25
-3
lines changed

2 files changed

+25
-3
lines changed

java/gazelle/private/servermanager/servermanager.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,13 @@ func (m *ServerManager) Shutdown() {
137137

138138
cc := pb.NewLifecycleClient(m.conn)
139139

140-
// If shutdown returns an error, there's really nothing for us to do.
141-
cc.Shutdown(context.Background(), &pb.ShutdownRequest{})
140+
// Ask the server to shut down, but don't block indefinitely.
141+
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
142+
defer cancel()
143+
_, _ = cc.Shutdown(ctx, &pb.ShutdownRequest{})
144+
145+
// Give the server a brief moment to send GOAWAY and close cleanly to avoid DEBUG stacktraces.
146+
time.Sleep(100 * time.Millisecond)
142147

143148
m.conn.Close()
144149

java/src/com/github/bazel_contrib/contrib_rules_jvm/javaparser/generators/LifecycleService.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,23 @@ public class LifecycleService extends LifecycleGrpc.LifecycleImplBase {
99

1010
@Override
1111
public void shutdown(ShutdownRequest request, StreamObserver<ShutdownResponse> responseObserver) {
12-
System.exit(0);
12+
// Reply to the RPC so the client doesn't block waiting for a response.
13+
try {
14+
responseObserver.onNext(ShutdownResponse.newBuilder().build());
15+
responseObserver.onCompleted();
16+
} finally {
17+
// Exit on a separate thread shortly after completing the response, to allow gRPC
18+
// to flush frames and the client to process the response without waiting on shutdown.
19+
new Thread(
20+
() -> {
21+
try {
22+
Thread.sleep(50);
23+
} catch (InterruptedException ignored) {
24+
}
25+
System.exit(0);
26+
},
27+
"LifecycleShutdownExit")
28+
.start();
29+
}
1330
}
1431
}

0 commit comments

Comments
 (0)