@@ -69,8 +69,6 @@ cgrpc_channel *cgrpc_channel_create_secure(const char *address,
void cgrpc_channel_destroy(cgrpc_channel *c) {
grpc_channel_destroy(c->channel);
c->channel = NULL;
-
- grpc_completion_queue_shutdown(c->completion_queue);
free(c);
}
@@ -32,7 +32,6 @@ cgrpc_handler *cgrpc_handler_create_with_server(cgrpc_server *server) {
void cgrpc_handler_destroy(cgrpc_handler *h) {
- grpc_completion_queue_shutdown(h->completion_queue);
grpc_metadata_array_destroy(&(h->request_metadata_recv));
grpc_call_details_destroy(&(h->call_details));
if (h->server_call) {
@@ -75,8 +75,6 @@ void cgrpc_server_destroy(cgrpc_server *server) {
grpc_server_destroy(server->server);
server->server = NULL;
- grpc_completion_queue_shutdown(server->completion_queue);
void cgrpc_server_start(cgrpc_server *server) {
@@ -66,8 +66,8 @@ public class Channel {
deinit {
- completionQueue.shutdown()
cgrpc_channel_destroy(underlyingChannel)
+ completionQueue.shutdown()
/// Constructs a Call object to make a gRPC API call
@@ -162,9 +162,15 @@ class CompletionQueue {
/// Shuts down a completion queue
func shutdown() {
+ var needsShutdown = false
operationGroupsMutex.synchronize {
- hasBeenShutdown = true
+ if !hasBeenShutdown {
+ needsShutdown = true
+ hasBeenShutdown = true
+ }
+ if needsShutdown {
+ cgrpc_completion_queue_shutdown(underlyingCompletionQueue)
- cgrpc_completion_queue_shutdown(underlyingCompletionQueue)
@@ -70,6 +70,9 @@ public class Handler {
+ // Technically unnecessary, because the handler only gets released once the completion queue has already been
+ // shut down, but it doesn't hurt to keep this here.
cgrpc_handler_destroy(self.underlyingHandler)
@@ -58,6 +58,7 @@ public class Server {
cgrpc_server_destroy(underlyingServer)
/// Run the server