Fix call destruction bug

pull/10468/head
murgatroid99 8 years ago
parent 81ff57f1c3
commit 130568e515
  1. 10
      src/node/ext/call.cc
  2. 5
      src/node/ext/call.h
  3. 2
      src/node/ext/channel.cc
  4. 4
      src/node/ext/server.cc
  5. 3
      src/node/ext/server_uv.cc

@ -466,8 +466,10 @@ class ServerCloseResponseOp : public Op {
int cancelled; int cancelled;
}; };
tag::tag(Callback *callback, OpVec *ops, Call *call) : tag::tag(Callback *callback, OpVec *ops, Call *call, Local<Value> call_value) :
callback(callback), ops(ops), call(call){ callback(callback), ops(ops), call(call){
HandleScope scope;
call_persist.Reset(call_value);
} }
tag::~tag() { tag::~tag() {
@ -521,6 +523,7 @@ Call::Call(grpc_call *call) : wrapped_call(call),
Call::~Call() { Call::~Call() {
if (wrapped_call != NULL) { if (wrapped_call != NULL) {
grpc_call_destroy(wrapped_call); grpc_call_destroy(wrapped_call);
wrapped_call = NULL;
} }
} }
@ -567,7 +570,8 @@ void Call::CompleteBatch(bool is_final_op) {
this->has_final_op_completed = true; this->has_final_op_completed = true;
} }
this->pending_batches--; this->pending_batches--;
if (this->has_final_op_completed && this->pending_batches == 0) { if (this->has_final_op_completed && this->pending_batches == 0 &&
this->wrapped_call != NULL) {
grpc_call_destroy(this->wrapped_call); grpc_call_destroy(this->wrapped_call);
this->wrapped_call = NULL; this->wrapped_call = NULL;
} }
@ -721,7 +725,7 @@ NAN_METHOD(Call::StartBatch) {
Callback *callback = new Callback(callback_func); Callback *callback = new Callback(callback_func);
grpc_call_error error = grpc_call_start_batch( grpc_call_error error = grpc_call_start_batch(
call->wrapped_call, &ops[0], nops, new struct tag( call->wrapped_call, &ops[0], nops, new struct tag(
callback, op_vector.release(), call), NULL); callback, op_vector.release(), call, info.This()), NULL);
if (error != GRPC_CALL_OK) { if (error != GRPC_CALL_OK) {
return Nan::ThrowError(nanErrorWithCode("startBatch failed", error)); return Nan::ThrowError(nanErrorWithCode("startBatch failed", error));
} }

@ -109,11 +109,14 @@ class Op {
typedef std::vector<unique_ptr<Op>> OpVec; typedef std::vector<unique_ptr<Op>> OpVec;
struct tag { struct tag {
tag(Nan::Callback *callback, OpVec *ops, Call *call); tag(Nan::Callback *callback, OpVec *ops, Call *call,
v8::Local<v8::Value> call_value);
~tag(); ~tag();
Nan::Callback *callback; Nan::Callback *callback;
OpVec *ops; OpVec *ops;
Call *call; Call *call;
Nan::Persistent<v8::Value, Nan::CopyablePersistentTraits<v8::Value>>
call_persist;
}; };
v8::Local<v8::Value> GetTagNodeValue(void *tag); v8::Local<v8::Value> GetTagNodeValue(void *tag);

@ -280,7 +280,7 @@ NAN_METHOD(Channel::WatchConnectivityState) {
channel->wrapped_channel, last_state, MillisecondsToTimespec(deadline), channel->wrapped_channel, last_state, MillisecondsToTimespec(deadline),
GetCompletionQueue(), GetCompletionQueue(),
new struct tag(callback, new struct tag(callback,
ops.release(), NULL)); ops.release(), NULL, Nan::Null()));
CompletionQueueNext(); CompletionQueueNext();
} }

@ -193,7 +193,7 @@ NAN_METHOD(Server::RequestCall) {
GetCompletionQueue(), GetCompletionQueue(),
GetCompletionQueue(), GetCompletionQueue(),
new struct tag(new Callback(info[0].As<Function>()), ops.release(), new struct tag(new Callback(info[0].As<Function>()), ops.release(),
NULL)); NULL, Nan::Null()));
if (error != GRPC_CALL_OK) { if (error != GRPC_CALL_OK) {
return Nan::ThrowError(nanErrorWithCode("requestCall failed", error)); return Nan::ThrowError(nanErrorWithCode("requestCall failed", error));
} }
@ -246,7 +246,7 @@ NAN_METHOD(Server::TryShutdown) {
grpc_server_shutdown_and_notify( grpc_server_shutdown_and_notify(
server->wrapped_server, GetCompletionQueue(), server->wrapped_server, GetCompletionQueue(),
new struct tag(new Nan::Callback(info[0].As<Function>()), ops.release(), new struct tag(new Nan::Callback(info[0].As<Function>()), ops.release(),
NULL)); NULL, Nan::Null()));
CompletionQueueNext(); CompletionQueueNext();
} }

@ -118,7 +118,8 @@ void Server::ShutdownServer() {
grpc_server_shutdown_and_notify( grpc_server_shutdown_and_notify(
this->wrapped_server, GetCompletionQueue(), this->wrapped_server, GetCompletionQueue(),
new struct tag(new Callback(**shutdown_callback), ops.release(), NULL)); new struct tag(new Callback(**shutdown_callback), ops.release(), NULL,
Nan::Null()));
grpc_server_cancel_all_calls(this->wrapped_server); grpc_server_cancel_all_calls(this->wrapped_server);
CompletionQueueNext(); CompletionQueueNext();
this->wrapped_server = NULL; this->wrapped_server = NULL;

Loading…
Cancel
Save