Fix segfault in Node server destructor

pull/9766/head
murgatroid99 8 years ago
parent 009c859832
commit acd0ba0ca3
  1. 2
      binding.gyp
  2. 2
      build.yaml
  3. 69
      src/node/ext/server.cc
  4. 1
      src/node/ext/server.h
  5. 73
      src/node/ext/server_generic.cc
  6. 133
      src/node/ext/server_uv.cc

@ -879,6 +879,8 @@
"src/node/ext/node_grpc.cc",
"src/node/ext/server.cc",
"src/node/ext/server_credentials.cc",
"src/node/ext/server_generic.cc",
"src/node/ext/server_uv.cc",
"src/node/ext/timeval.cc",
],
"dependencies": [

@ -3946,6 +3946,8 @@ node_modules:
- src/node/ext/node_grpc.cc
- src/node/ext/server.cc
- src/node/ext/server_credentials.cc
- src/node/ext/server_generic.cc
- src/node/ext/server_uv.cc
- src/node/ext/timeval.cc
openssl_fallback:
base_uri: https://openssl.org/source/old/1.0.2/

@ -77,8 +77,6 @@ using v8::Value;
Nan::Callback *Server::constructor;
Persistent<FunctionTemplate> Server::fun_tpl;
static Callback *shutdown_callback;
class NewCallOp : public Op {
public:
NewCallOp() {
@ -127,52 +125,6 @@ class NewCallOp : public Op {
std::string GetTypeString() const { return "new_call"; }
};
class ServerShutdownOp : public Op {
public:
ServerShutdownOp(grpc_server *server): server(server) {
}
~ServerShutdownOp() {
}
Local<Value> GetNodeValue() const {
return Nan::New<External>(reinterpret_cast<void *>(server));
}
bool ParseOp(Local<Value> value, grpc_op *out,
shared_ptr<Resources> resources) {
return true;
}
bool IsFinalOp() {
return false;
}
grpc_server *server;
protected:
std::string GetTypeString() const { return "shutdown"; }
};
NAN_METHOD(ServerShutdownCallback) {
if (!info[0]->IsNull()) {
return Nan::ThrowError("forceShutdown failed somehow");
}
MaybeLocal<Object> maybe_result = Nan::To<Object>(info[1]);
Local<Object> result = maybe_result.ToLocalChecked();
Local<Value> server_val = Nan::Get(
result, Nan::New("shutdown").ToLocalChecked()).ToLocalChecked();
Local<External> server_extern = server_val.As<External>();
grpc_server *server = reinterpret_cast<grpc_server *>(server_extern->Value());
grpc_server_destroy(server);
}
Server::Server(grpc_server *server) : wrapped_server(server) {
}
Server::~Server() {
this->ShutdownServer();
}
void Server::Init(Local<Object> exports) {
HandleScope scope;
Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
@ -187,11 +139,6 @@ void Server::Init(Local<Object> exports) {
Local<Function> ctr = Nan::GetFunction(tpl).ToLocalChecked();
Nan::Set(exports, Nan::New("Server").ToLocalChecked(), ctr);
constructor = new Callback(ctr);
Local<FunctionTemplate>callback_tpl =
Nan::New<FunctionTemplate>(ServerShutdownCallback);
shutdown_callback = new Callback(
Nan::GetFunction(callback_tpl).ToLocalChecked());
}
bool Server::HasInstance(Local<Value> val) {
@ -199,22 +146,6 @@ bool Server::HasInstance(Local<Value> val) {
return Nan::New(fun_tpl)->HasInstance(val);
}
void Server::ShutdownServer() {
if (this->wrapped_server != NULL) {
ServerShutdownOp *op = new ServerShutdownOp(this->wrapped_server);
unique_ptr<OpVec> ops(new OpVec());
ops->push_back(unique_ptr<Op>(op));
grpc_server_shutdown_and_notify(
this->wrapped_server, GetCompletionQueue(),
new struct tag(new Callback(**shutdown_callback), ops.release(),
shared_ptr<Resources>(nullptr), NULL));
grpc_server_cancel_all_calls(this->wrapped_server);
CompletionQueueNext();
this->wrapped_server = NULL;
}
}
NAN_METHOD(Server::New) {
/* If this is not a constructor call, make a constructor call and return
the result */

@ -73,6 +73,7 @@ class Server : public Nan::ObjectWrap {
static Nan::Persistent<v8::FunctionTemplate> fun_tpl;
grpc_server *wrapped_server;
grpc_completion_queue *shutdown_queue;
};
} // namespace node

@ -0,0 +1,73 @@
/*
*
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_UV
#include "server.h"
#include <node.h>
#include <nan.h>
#include "grpc/grpc.h"
#include "grpc/support/time.h"
namespace grpc {
namespace node {
Server::Server(grpc_server *server) : wrapped_server(server) {
shutdown_queue = grpc_completion_queue_create(NULL);
grpc_server_register_non_listening_completion_queue(server, shutdown_queue,
NULL);
}
Server::~Server() {
this->ShutdownServer();
grpc_completion_queue_shutdown(this->shutdown_queue);
grpc_completion_queue_destroy(this->shutdown_queue);
}
void Server::ShutdownServer() {
if (this->wrapped_server != NULL) {
grpc_server_shutdown_and_notify(this->wrapped_server, this->shutdown_queue,
NULL);
grpc_server_cancel_all_calls(this->wrapped_server);
grpc_completion_queue_pluck(this->shutdown_queue, NULL,
gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
grpc_server_destroy(this->wrapped_server);
this->wrapped_server = NULL;
}
}
} // namespace grpc
} // namespace node
#endif /* GRPC_UV */

@ -0,0 +1,133 @@
/*
*
* Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef GRPC_UV
#include "server.h"
#include <node.h>
#include <nan.h>
#include "grpc/grpc.h"
#include "grpc/support/time.h"
#include "call.h"
#include "completion_queue.h"
namespace grpc {
namespace node {
using Nan::Callback;
using v8::External;
using v8::Function;
using v8::FunctionTemplate;
using v8::Local;
using v8::MaybeLocal;
using v8::Object;
using v8::Value;
static Callback *shutdown_callback = NULL;
class ServerShutdownOp : public Op {
public:
ServerShutdownOp(grpc_server *server): server(server) {
}
~ServerShutdownOp() {
}
Local<Value> GetNodeValue() const {
return Nan::New<External>(reinterpret_cast<void *>(server));
}
bool ParseOp(Local<Value> value, grpc_op *out,
shared_ptr<Resources> resources) {
return true;
}
bool IsFinalOp() {
return false;
}
grpc_server *server;
protected:
std::string GetTypeString() const { return "shutdown"; }
};
Server::Server(grpc_server *server) : wrapped_server(server) {
}
Server::~Server() {
this->ShutdownServer();
}
NAN_METHOD(ServerShutdownCallback) {
if (!info[0]->IsNull()) {
return Nan::ThrowError("forceShutdown failed somehow");
}
MaybeLocal<Object> maybe_result = Nan::To<Object>(info[1]);
Local<Object> result = maybe_result.ToLocalChecked();
Local<Value> server_val = Nan::Get(
result, Nan::New("shutdown").ToLocalChecked()).ToLocalChecked();
Local<External> server_extern = server_val.As<External>();
grpc_server *server = reinterpret_cast<grpc_server *>(server_extern->Value());
grpc_server_destroy(server);
}
void Server::ShutdownServer() {
if (this->wrapped_server != NULL) {
if (shutdown_callback == NULL) {
Local<FunctionTemplate>callback_tpl =
Nan::New<FunctionTemplate>(ServerShutdownCallback);
shutdown_callback = new Callback(
Nan::GetFunction(callback_tpl).ToLocalChecked());
}
ServerShutdownOp *op = new ServerShutdownOp(this->wrapped_server);
unique_ptr<OpVec> ops(new OpVec());
ops->push_back(unique_ptr<Op>(op));
grpc_server_shutdown_and_notify(
this->wrapped_server, GetCompletionQueue(),
new struct tag(new Callback(**shutdown_callback), ops.release(),
shared_ptr<Resources>(nullptr), NULL));
grpc_server_cancel_all_calls(this->wrapped_server);
CompletionQueueNext();
this->wrapped_server = NULL;
}
}
} // namespace grpc
} // namespace node
#endif /* GRPC_UV */
Loading…
Cancel
Save