ForberichN
ForberichN

Reputation: 50

Java GRPC spawns to many new threads (Minecraft Spigot Plugin)

I'm writing a Spigot plugin that Sends and Receives Messages via GRPC. My problem is that after a view hours the server Crashes because the process can't open more file hanldes for new threads. From looking at some thread dumps it seems that GRPC is spawning multiple threads per Second without ever Closing them. The Code im using to receive the message stream looks like the following:

public class GRPCMessageReceiver extends BukkitRunnable {

ChatSyncGrpc.ChatSyncBlockingStub chatSync;
LockedQueue lockedQueue = new LockedQueue();
Iterator<ChatMessage> receivingIterator;

public GRPCMessageReceiver(ChatSyncGrpc.ChatSyncBlockingStub chatSync, LockedQueue queue){
    lockedQueue = queue;
    this.chatSync = chatSync;
}

@Override
public void run() {
    if (receivingIterator == null) receivingIterator = chatSync.beginReceive(Empty.newBuilder().build());
    try {
        if (receivingIterator.hasNext()) {
            ChatMessage message = receivingIterator.next();
            lockedQueue.Put(message);
            message.
        }
    } catch (io.grpc.StatusRuntimeException e) {
        receivingIterator = chatSync.beginReceive(Empty.newBuilder().build());
        Bukkit.getLogger().info("Chat Sync Connection Failed created new one!");
    }
}

} All Threads have the same Stack Trace:

  java.lang.Thread.State: WAITING
  at jdk.internal.misc.Unsafe.park(Unsafe.java:-1)
  at java.util.concurrent.locks.LockSupport.park(LockSupport.java:211)
  at io.grpc.stub.ClientCalls$ThreadlessExecutor.waitAndDrain(ClientCalls.java:731)
  at io.grpc.stub.ClientCalls$BlockingResponseStream.waitForNext(ClientCalls.java:622)
  at io.grpc.stub.ClientCalls$BlockingResponseStream.hasNext(ClientCalls.java:643)
  at HausSheepPlugin.GRPCMessageReceiver.run(GRPCMessageReceiver.java:26)
  at org.bukkit.craftbukkit.v1_16_R2.scheduler.CraftTask.run(CraftTask.java:81)
  at org.bukkit.craftbukkit.v1_16_R2.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:54)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
  at java.lang.Thread.run(Thread.java:832)

Is this a problem on my side or on GRPCs side?

Upvotes: 0

Views: 778

Answers (1)

Louis Wasserman
Louis Wasserman

Reputation: 198471

hasNext() waits until an element arrives or the stream is closed.

If an element just hasn't arrived yet, it will sit around waiting until another element arrives. When many calls do that, you get more threads waiting than elements, so threads keep stacking up.

So, more or less: you shouldn't be structuring your receipt of the stream this way. Either use the async API and a StreamObserver -- which seems to match your code's needs anyway -- or have run() consume the entire iterator, instead of trying to just consume one element.

Upvotes: 2

Related Questions