Merge pull request #10598 from jtattermusch/manual_upmerge_v12x
Manual upmerge from v1.2.x
diff --git a/BUILD b/BUILD
index ab4c1cf..1432288 100644
--- a/BUILD
+++ b/BUILD
@@ -457,7 +457,6 @@
"src/core/lib/iomgr/endpoint_pair_windows.c",
"src/core/lib/iomgr/error.c",
"src/core/lib/iomgr/ev_epoll_linux.c",
- "src/core/lib/iomgr/lockfree_event.c",
"src/core/lib/iomgr/ev_poll_posix.c",
"src/core/lib/iomgr/ev_posix.c",
"src/core/lib/iomgr/exec_ctx.c",
@@ -468,6 +467,7 @@
"src/core/lib/iomgr/iomgr_uv.c",
"src/core/lib/iomgr/iomgr_windows.c",
"src/core/lib/iomgr/load_file.c",
+ "src/core/lib/iomgr/lockfree_event.c",
"src/core/lib/iomgr/network_status_tracker.c",
"src/core/lib/iomgr/polling_entity.c",
"src/core/lib/iomgr/pollset_set_uv.c",
@@ -584,7 +584,6 @@
"src/core/lib/iomgr/error.h",
"src/core/lib/iomgr/error_internal.h",
"src/core/lib/iomgr/ev_epoll_linux.h",
- "src/core/lib/iomgr/lockfree_event.h",
"src/core/lib/iomgr/ev_poll_posix.h",
"src/core/lib/iomgr/ev_posix.h",
"src/core/lib/iomgr/exec_ctx.h",
@@ -594,6 +593,7 @@
"src/core/lib/iomgr/iomgr_internal.h",
"src/core/lib/iomgr/iomgr_posix.h",
"src/core/lib/iomgr/load_file.h",
+ "src/core/lib/iomgr/lockfree_event.h",
"src/core/lib/iomgr/network_status_tracker.h",
"src/core/lib/iomgr/polling_entity.h",
"src/core/lib/iomgr/pollset.h",
diff --git a/examples/csharp/helloworld-from-cli/global.json b/examples/csharp/helloworld-from-cli/global.json
index 32ff399..f3c33ce 100644
--- a/examples/csharp/helloworld-from-cli/global.json
+++ b/examples/csharp/helloworld-from-cli/global.json
@@ -1,5 +1,5 @@
{
"sdk": {
- "version": "1.0.0-preview2-003121"
+ "version": "1.0.0-preview2-003131"
}
}
\ No newline at end of file
diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c
index 57726c8..c12fabb 100644
--- a/src/core/lib/channel/message_size_filter.c
+++ b/src/core/lib/channel/message_size_filter.c
@@ -218,14 +218,14 @@
if (strcmp(args->channel_args->args[i].key,
GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) == 0) {
const grpc_integer_options options = {
- GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH, 0, INT_MAX};
+ GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH, -1, INT_MAX};
chand->max_send_size =
grpc_channel_arg_get_integer(&args->channel_args->args[i], options);
}
if (strcmp(args->channel_args->args[i].key,
GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH) == 0) {
const grpc_integer_options options = {
- GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH, 0, INT_MAX};
+ GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH, -1, INT_MAX};
chand->max_recv_size =
grpc_channel_arg_get_integer(&args->channel_args->args[i], options);
}
diff --git a/src/core/lib/iomgr/resolve_address_uv.c b/src/core/lib/iomgr/resolve_address_uv.c
index 102d1aa..6b46876 100644
--- a/src/core/lib/iomgr/resolve_address_uv.c
+++ b/src/core/lib/iomgr/resolve_address_uv.c
@@ -69,8 +69,9 @@
int retry_status;
uv_getaddrinfo_t *req = gpr_malloc(sizeof(uv_getaddrinfo_t));
req->data = r;
+ r->port = svc[i][1];
retry_status = uv_getaddrinfo(uv_default_loop(), req, getaddrinfo_cb,
- r->host, svc[i][1], r->hints);
+ r->host, r->port, r->hints);
if (retry_status < 0 || getaddrinfo_cb == NULL) {
// The callback will not be called
gpr_free(req);
diff --git a/src/csharp/Grpc.Auth/project.json b/src/csharp/Grpc.Auth/project.json
deleted file mode 100644
index 370bf11..0000000
--- a/src/csharp/Grpc.Auth/project.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
- "version": "1.3.0-dev",
- "title": "gRPC C# Auth",
- "authors": [ "Google Inc." ],
- "copyright": "Copyright 2015, Google Inc.",
- "packOptions": {
- "summary": "Auth library for C# implementation of gRPC - an RPC library and framework",
- "description": "Auth library for C# implementation of gRPC - an RPC library and framework. See project site for more info.",
- "owners": [ "grpc-packages" ],
- "licenseUrl": "https://github.com/grpc/grpc/blob/master/LICENSE",
- "projectUrl": "https://github.com/grpc/grpc",
- "requireLicenseAcceptance": false,
- "tags": [ "gRPC RPC Protocol HTTP/2 Auth OAuth2" ],
- },
- "buildOptions": {
- "define": [ "SIGNED" ],
- "keyFile": "../keys/Grpc.snk",
- "xmlDoc": true,
- "compile": {
- "includeFiles": [ "../Grpc.Core/Version.cs" ]
- }
- },
- "dependencies": {
- "Grpc.Core": "1.3.0-dev",
- "Google.Apis.Auth": "1.21.0"
- },
- "frameworks": {
- "net45": { },
- "netstandard1.5": {
- "dependencies": {
- "NETStandard.Library": "1.6.0"
- }
- }
- }
-}
diff --git a/src/csharp/Grpc.Core.Testing/project.json b/src/csharp/Grpc.Core.Testing/project.json
deleted file mode 100644
index 38d5fab..0000000
--- a/src/csharp/Grpc.Core.Testing/project.json
+++ /dev/null
@@ -1,39 +0,0 @@
-{
- "version": "1.3.0-dev",
- "title": "gRPC C# Core Testing",
- "authors": [ "Google Inc." ],
- "copyright": "Copyright 2017, Google Inc.",
- "packOptions": {
- "summary": "Testing support for gRPC C#",
- "description": "Useful when testing code that uses gRPC.",
- "owners": [ "grpc-packages" ],
- "licenseUrl": "https://github.com/grpc/grpc/blob/master/LICENSE",
- "projectUrl": "https://github.com/grpc/grpc",
- "requireLicenseAcceptance": false,
- "tags": [ "gRPC test testing" ]
- },
- "buildOptions": {
- "define": [ "SIGNED" ],
- "keyFile": "../keys/Grpc.snk",
- "xmlDoc": true,
- "compile": {
- "includeFiles": [ "../Grpc.Core/Version.cs" ]
- }
- },
- "dependencies": {
- "Grpc.Core": "1.3.0-dev"
- },
- "frameworks": {
- "net45": {
- "frameworkAssemblies": {
- "System.Runtime": "",
- "System.IO": ""
- }
- },
- "netstandard1.5": {
- "dependencies": {
- "NETStandard.Library": "1.6.0"
- }
- }
- }
-}
diff --git a/src/csharp/Grpc.HealthCheck/project.json b/src/csharp/Grpc.HealthCheck/project.json
deleted file mode 100644
index e93d0bf..0000000
--- a/src/csharp/Grpc.HealthCheck/project.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
- "version": "1.3.0-dev",
- "title": "gRPC C# Healthchecking",
- "authors": [ "Google Inc." ],
- "copyright": "Copyright 2015, Google Inc.",
- "packOptions": {
- "summary": "Implementation of gRPC health service",
- "description": "Example implementation of grpc.health.v1 service that can be used for health-checking.",
- "owners": [ "grpc-packages" ],
- "licenseUrl": "https://github.com/grpc/grpc/blob/master/LICENSE",
- "projectUrl": "https://github.com/grpc/grpc",
- "requireLicenseAcceptance": false,
- "tags": [ "gRPC health check" ]
- },
- "buildOptions": {
- "define": [ "SIGNED" ],
- "keyFile": "../keys/Grpc.snk",
- "xmlDoc": true,
- "compile": {
- "includeFiles": [ "../Grpc.Core/Version.cs" ]
- }
- },
- "dependencies": {
- "Grpc.Core": "1.3.0-dev",
- "Google.Protobuf": "3.2.0"
- },
- "frameworks": {
- "net45": {},
- "netstandard1.5": {
- "dependencies": {
- "NETStandard.Library": "1.6.0"
- }
- }
- }
-}
diff --git a/src/csharp/Grpc.Reflection/project.json b/src/csharp/Grpc.Reflection/project.json
deleted file mode 100644
index 014c78e..0000000
--- a/src/csharp/Grpc.Reflection/project.json
+++ /dev/null
@@ -1,35 +0,0 @@
-{
- "version": "1.3.0-dev",
- "title": "gRPC C# Reflection",
- "authors": [ "Google Inc." ],
- "copyright": "Copyright 2016, Google Inc.",
- "packOptions": {
- "summary": "Implementation of gRPC reflection service",
- "description": "Provides information about services running on a gRPC C# server.",
- "owners": [ "grpc-packages" ],
- "licenseUrl": "https://github.com/grpc/grpc/blob/master/LICENSE",
- "projectUrl": "https://github.com/grpc/grpc",
- "requireLicenseAcceptance": false,
- "tags": [ "gRPC reflection" ]
- },
- "buildOptions": {
- "define": [ "SIGNED" ],
- "keyFile": "../keys/Grpc.snk",
- "xmlDoc": true,
- "compile": {
- "includeFiles": [ "../Grpc.Core/Version.cs" ]
- }
- },
- "dependencies": {
- "Grpc.Core": "1.3.0-dev",
- "Google.Protobuf": "3.2.0"
- },
- "frameworks": {
- "net45": {},
- "netstandard1.5": {
- "dependencies": {
- "NETStandard.Library": "1.6.0"
- }
- }
- }
-}
diff --git a/src/csharp/global.json b/src/csharp/global.json
new file mode 100644
index 0000000..f3c33ce
--- /dev/null
+++ b/src/csharp/global.json
@@ -0,0 +1,5 @@
+{
+ "sdk": {
+ "version": "1.0.0-preview2-003131"
+ }
+}
\ No newline at end of file
diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc
index 244546d..5d57311 100644
--- a/src/node/ext/call.cc
+++ b/src/node/ext/call.cc
@@ -99,7 +99,6 @@
bool CreateMetadataArray(Local<Object> metadata, grpc_metadata_array *array) {
HandleScope scope;
- grpc_metadata_array_init(array);
Local<Array> keys = Nan::GetOwnPropertyNames(metadata).ToLocalChecked();
for (unsigned int i = 0; i < keys->Length(); i++) {
Local<String> current_key = Nan::To<String>(
@@ -111,18 +110,20 @@
array->capacity += Local<Array>::Cast(value_array)->Length();
}
array->metadata = reinterpret_cast<grpc_metadata*>(
- gpr_malloc(array->capacity * sizeof(grpc_metadata)));
+ gpr_zalloc(array->capacity * sizeof(grpc_metadata)));
for (unsigned int i = 0; i < keys->Length(); i++) {
Local<String> current_key(Nan::To<String>(keys->Get(i)).ToLocalChecked());
Local<Array> values = Local<Array>::Cast(
Nan::Get(metadata, current_key).ToLocalChecked());
- grpc_slice key_slice = grpc_slice_intern(CreateSliceFromString(current_key));
+ grpc_slice key_slice = CreateSliceFromString(current_key);
+ grpc_slice key_intern_slice = grpc_slice_intern(key_slice);
+ grpc_slice_unref(key_slice);
for (unsigned int j = 0; j < values->Length(); j++) {
Local<Value> value = Nan::Get(values, j).ToLocalChecked();
grpc_metadata *current = &array->metadata[array->count];
- current->key = key_slice;
+ current->key = key_intern_slice;
// Only allow binary headers for "-bin" keys
- if (grpc_is_binary_header(key_slice)) {
+ if (grpc_is_binary_header(key_intern_slice)) {
if (::node::Buffer::HasInstance(value)) {
current->value = CreateSliceFromBuffer(value);
} else {
@@ -142,6 +143,14 @@
return true;
}
+void DestroyMetadataArray(grpc_metadata_array *array) {
+ for (size_t i = 0; i < array->count; i++) {
+ // Don't unref keys because they are interned
+ grpc_slice_unref(array->metadata[i].value);
+ }
+ grpc_metadata_array_destroy(array);
+}
+
Local<Value> ParseMetadata(const grpc_metadata_array *metadata_array) {
EscapableHandleScope scope;
grpc_metadata *metadata_elements = metadata_array->metadata;
@@ -179,6 +188,12 @@
class SendMetadataOp : public Op {
public:
+ SendMetadataOp() {
+ grpc_metadata_array_init(&send_metadata);
+ }
+ ~SendMetadataOp() {
+ DestroyMetadataArray(&send_metadata);
+ }
Local<Value> GetNodeValue() const {
EscapableHandleScope scope;
return scope.Escape(Nan::True());
@@ -187,17 +202,16 @@
if (!value->IsObject()) {
return false;
}
- grpc_metadata_array array;
MaybeLocal<Object> maybe_metadata = Nan::To<Object>(value);
if (maybe_metadata.IsEmpty()) {
return false;
}
if (!CreateMetadataArray(maybe_metadata.ToLocalChecked(),
- &array)) {
+ &send_metadata)) {
return false;
}
- out->data.send_initial_metadata.count = array.count;
- out->data.send_initial_metadata.metadata = array.metadata;
+ out->data.send_initial_metadata.count = send_metadata.count;
+ out->data.send_initial_metadata.metadata = send_metadata.metadata;
return true;
}
bool IsFinalOp() {
@@ -207,6 +221,8 @@
std::string GetTypeString() const {
return "send_metadata";
}
+ private:
+ grpc_metadata_array send_metadata;
};
class SendMessageOp : public Op {
@@ -272,8 +288,12 @@
class SendServerStatusOp : public Op {
public:
+ SendServerStatusOp() {
+ grpc_metadata_array_init(&status_metadata);
+ }
~SendServerStatusOp() {
grpc_slice_unref(details);
+ DestroyMetadataArray(&status_metadata);
}
Local<Value> GetNodeValue() const {
EscapableHandleScope scope;
@@ -313,12 +333,13 @@
}
Local<String> details = Nan::To<String>(
maybe_details.ToLocalChecked()).ToLocalChecked();
- grpc_metadata_array array;
- if (!CreateMetadataArray(metadata, &array)) {
+ if (!CreateMetadataArray(metadata, &status_metadata)) {
return false;
}
- out->data.send_status_from_server.trailing_metadata_count = array.count;
- out->data.send_status_from_server.trailing_metadata = array.metadata;
+ out->data.send_status_from_server.trailing_metadata_count =
+ status_metadata.count;
+ out->data.send_status_from_server.trailing_metadata =
+ status_metadata.metadata;
out->data.send_status_from_server.status =
static_cast<grpc_status_code>(code);
this->details = CreateSliceFromString(details);
@@ -335,6 +356,7 @@
private:
grpc_slice details;
+ grpc_metadata_array status_metadata;
};
class GetMetadataOp : public Op {
@@ -466,8 +488,10 @@
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){
+ HandleScope scope;
+ call_persist.Reset(call_value);
}
tag::~tag() {
@@ -513,15 +537,20 @@
delete tag_struct;
}
+void Call::DestroyCall() {
+ if (this->wrapped_call != NULL) {
+ grpc_call_destroy(this->wrapped_call);
+ this->wrapped_call = NULL;
+ }
+}
+
Call::Call(grpc_call *call) : wrapped_call(call),
pending_batches(0),
has_final_op_completed(false) {
}
Call::~Call() {
- if (wrapped_call != NULL) {
- grpc_call_destroy(wrapped_call);
- }
+ DestroyCall();
}
void Call::Init(Local<Object> exports) {
@@ -568,12 +597,19 @@
}
this->pending_batches--;
if (this->has_final_op_completed && this->pending_batches == 0) {
- grpc_call_destroy(this->wrapped_call);
- this->wrapped_call = NULL;
+ this->DestroyCall();
}
}
NAN_METHOD(Call::New) {
+ /* Arguments:
+ * 0: Channel to make the call on
+ * 1: Method
+ * 2: Deadline
+ * 3: host
+ * 4: parent Call
+ * 5: propagation flags
+ */
if (info.IsConstructCall()) {
Call *call;
if (info[0]->IsExternal()) {
@@ -618,25 +654,26 @@
double deadline = Nan::To<double>(info[2]).FromJust();
grpc_channel *wrapped_channel = channel->GetWrappedChannel();
grpc_call *wrapped_call;
+ grpc_slice method = CreateSliceFromString(
+ Nan::To<String>(info[1]).ToLocalChecked());
if (info[3]->IsString()) {
grpc_slice *host = new grpc_slice;
*host = CreateSliceFromString(
Nan::To<String>(info[3]).ToLocalChecked());
wrapped_call = grpc_channel_create_call(
wrapped_channel, parent_call, propagate_flags,
- GetCompletionQueue(), CreateSliceFromString(
- Nan::To<String>(info[1]).ToLocalChecked()),
+ GetCompletionQueue(), method,
host, MillisecondsToTimespec(deadline), NULL);
delete host;
} else if (info[3]->IsUndefined() || info[3]->IsNull()) {
wrapped_call = grpc_channel_create_call(
wrapped_channel, parent_call, propagate_flags,
- GetCompletionQueue(), CreateSliceFromString(
- Nan::To<String>(info[1]).ToLocalChecked()),
+ GetCompletionQueue(), method,
NULL, MillisecondsToTimespec(deadline), NULL);
} else {
return Nan::ThrowTypeError("Call's fourth argument must be a string");
}
+ grpc_slice_unref(method);
call = new Call(wrapped_call);
Nan::Set(info.This(), Nan::New("channel_").ToLocalChecked(),
channel_object);
@@ -721,7 +758,7 @@
Callback *callback = new Callback(callback_func);
grpc_call_error error = grpc_call_start_batch(
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) {
return Nan::ThrowError(nanErrorWithCode("startBatch failed", error));
}
diff --git a/src/node/ext/call.h b/src/node/ext/call.h
index cffff00..53a5e4a 100644
--- a/src/node/ext/call.h
+++ b/src/node/ext/call.h
@@ -58,6 +58,8 @@
bool CreateMetadataArray(v8::Local<v8::Object> metadata,
grpc_metadata_array *array);
+void DestroyMetadataArray(grpc_metadata_array *array);
+
/* Wrapper class for grpc_call structs. */
class Call : public Nan::ObjectWrap {
public:
@@ -76,6 +78,8 @@
Call(const Call &);
Call &operator=(const Call &);
+ void DestroyCall();
+
static NAN_METHOD(New);
static NAN_METHOD(StartBatch);
static NAN_METHOD(Cancel);
@@ -109,11 +113,14 @@
typedef std::vector<unique_ptr<Op>> OpVec;
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();
Nan::Callback *callback;
OpVec *ops;
Call *call;
+ Nan::Persistent<v8::Value, Nan::CopyablePersistentTraits<v8::Value>>
+ call_persist;
};
v8::Local<v8::Value> GetTagNodeValue(void *tag);
diff --git a/src/node/ext/call_credentials.cc b/src/node/ext/call_credentials.cc
index afcc363..5bd4bdc 100644
--- a/src/node/ext/call_credentials.cc
+++ b/src/node/ext/call_credentials.cc
@@ -211,6 +211,7 @@
Utf8String details_utf8_str(info[1]);
char *details = *details_utf8_str;
grpc_metadata_array array;
+ grpc_metadata_array_init(&array);
Local<Object> callback_data = Nan::To<Object>(info[3]).ToLocalChecked();
if (!CreateMetadataArray(Nan::To<Object>(info[2]).ToLocalChecked(),
&array)){
@@ -226,6 +227,7 @@
Nan::New("user_data").ToLocalChecked()
).ToLocalChecked().As<External>()->Value();
cb(user_data, array.metadata, array.count, code, details);
+ DestroyMetadataArray(&array);
}
NAUV_WORK_CB(SendPluginCallback) {
diff --git a/src/node/ext/channel.cc b/src/node/ext/channel.cc
index c795ff7..1263cc0 100644
--- a/src/node/ext/channel.cc
+++ b/src/node/ext/channel.cc
@@ -280,7 +280,7 @@
channel->wrapped_channel, last_state, MillisecondsToTimespec(deadline),
GetCompletionQueue(),
new struct tag(callback,
- ops.release(), NULL));
+ ops.release(), NULL, Nan::Null()));
CompletionQueueNext();
}
diff --git a/src/node/ext/node_grpc.cc b/src/node/ext/node_grpc.cc
index 95e273f..122e5e6 100644
--- a/src/node/ext/node_grpc.cc
+++ b/src/node/ext/node_grpc.cc
@@ -286,8 +286,10 @@
"headerKeyIsLegal's argument must be a string");
}
Local<String> key = Nan::To<String>(info[0]).ToLocalChecked();
+ grpc_slice slice = CreateSliceFromString(key);
info.GetReturnValue().Set(static_cast<bool>(
- grpc_header_key_is_legal(CreateSliceFromString(key))));
+ grpc_header_key_is_legal(slice)));
+ grpc_slice_unref(slice);
}
NAN_METHOD(MetadataNonbinValueIsLegal) {
@@ -296,8 +298,10 @@
"metadataNonbinValueIsLegal's argument must be a string");
}
Local<String> value = Nan::To<String>(info[0]).ToLocalChecked();
+ grpc_slice slice = CreateSliceFromString(value);
info.GetReturnValue().Set(static_cast<bool>(
- grpc_header_nonbin_value_is_legal(CreateSliceFromString(value))));
+ grpc_header_nonbin_value_is_legal(slice)));
+ grpc_slice_unref(slice);
}
NAN_METHOD(MetadataKeyIsBinary) {
@@ -306,8 +310,10 @@
"metadataKeyIsLegal's argument must be a string");
}
Local<String> key = Nan::To<String>(info[0]).ToLocalChecked();
+ grpc_slice slice = CreateSliceFromString(key);
info.GetReturnValue().Set(static_cast<bool>(
- grpc_is_binary_header(CreateSliceFromString(key))));
+ grpc_is_binary_header(slice)));
+ grpc_slice_unref(slice);
}
static grpc_ssl_roots_override_result get_ssl_roots_override(
diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc
index ccb55aa..f0920c8 100644
--- a/src/node/ext/server.cc
+++ b/src/node/ext/server.cc
@@ -193,7 +193,7 @@
GetCompletionQueue(),
GetCompletionQueue(),
new struct tag(new Callback(info[0].As<Function>()), ops.release(),
- NULL));
+ NULL, Nan::Null()));
if (error != GRPC_CALL_OK) {
return Nan::ThrowError(nanErrorWithCode("requestCall failed", error));
}
@@ -246,7 +246,7 @@
grpc_server_shutdown_and_notify(
server->wrapped_server, GetCompletionQueue(),
new struct tag(new Nan::Callback(info[0].As<Function>()), ops.release(),
- NULL));
+ NULL, Nan::Null()));
CompletionQueueNext();
}
diff --git a/src/node/ext/server_uv.cc b/src/node/ext/server_uv.cc
index c5e5ca9..82e7589 100644
--- a/src/node/ext/server_uv.cc
+++ b/src/node/ext/server_uv.cc
@@ -118,7 +118,8 @@
grpc_server_shutdown_and_notify(
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);
CompletionQueueNext();
this->wrapped_server = NULL;