diff options
author | Michael Lumish <mlumish@google.com> | 2017-05-25 12:30:17 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-25 12:30:17 -0700 |
commit | 3410c8d7dc86fe7778d6795340d9792acb1b912b (patch) | |
tree | a3beb1986dbeac618bee824c955dc0d8027424cc /src | |
parent | ef2c85371dc15ce09a993410fc3313deee18df91 (diff) | |
parent | 30f2b7ece1d04502ef9a4345b88a76844ced9f2c (diff) |
Merge pull request #11304 from murgatroid99/node_call_lifetime_fixes
Add more null checks to call methods
Diffstat (limited to 'src')
-rw-r--r-- | src/node/ext/call.cc | 20 | ||||
-rw-r--r-- | src/node/ext/call.h | 1 | ||||
-rw-r--r-- | src/node/test/common_test.js | 1 | ||||
-rw-r--r-- | src/node/test/surface_test.js | 25 |
4 files changed, 43 insertions, 4 deletions
diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index 2cc9f63b65..e2185da1c5 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -562,10 +562,12 @@ void Call::DestroyCall() { Call::Call(grpc_call *call) : wrapped_call(call), pending_batches(0), has_final_op_completed(false) { + peer = grpc_call_get_peer(call); } Call::~Call() { DestroyCall(); + gpr_free(peer); } void Call::Init(Local<Object> exports) { @@ -794,6 +796,11 @@ NAN_METHOD(Call::Cancel) { return Nan::ThrowTypeError("cancel can only be called on Call objects"); } Call *call = ObjectWrap::Unwrap<Call>(info.This()); + if (call->wrapped_call == NULL) { + /* Cancel is supposed to be idempotent. If the call has already finished, + * cancel should just complete silently */ + return; + } grpc_call_error error = grpc_call_cancel(call->wrapped_call, NULL); if (error != GRPC_CALL_OK) { return Nan::ThrowError(nanErrorWithCode("cancel failed", error)); @@ -814,6 +821,11 @@ NAN_METHOD(Call::CancelWithStatus) { "cancelWithStatus's second argument must be a string"); } Call *call = ObjectWrap::Unwrap<Call>(info.This()); + if (call->wrapped_call == NULL) { + /* Cancel is supposed to be idempotent. If the call has already finished, + * cancel should just complete silently */ + return; + } grpc_status_code code = static_cast<grpc_status_code>( Nan::To<uint32_t>(info[0]).FromJust()); if (code == GRPC_STATUS_OK) { @@ -830,9 +842,7 @@ NAN_METHOD(Call::GetPeer) { return Nan::ThrowTypeError("getPeer can only be called on Call objects"); } Call *call = ObjectWrap::Unwrap<Call>(info.This()); - char *peer = grpc_call_get_peer(call->wrapped_call); - Local<Value> peer_value = Nan::New(peer).ToLocalChecked(); - gpr_free(peer); + Local<Value> peer_value = Nan::New(call->peer).ToLocalChecked(); info.GetReturnValue().Set(peer_value); } @@ -847,6 +857,10 @@ NAN_METHOD(Call::SetCredentials) { "setCredentials' first argument must be a CallCredentials"); } Call *call = ObjectWrap::Unwrap<Call>(info.This()); + if (call->wrapped_call == NULL) { + return Nan::ThrowError( + "Cannot set credentials on a call that has already started"); + } CallCredentials *creds_object = ObjectWrap::Unwrap<CallCredentials>( Nan::To<Object>(info[0]).ToLocalChecked()); grpc_call_credentials *creds = creds_object->GetWrappedCredentials(); diff --git a/src/node/ext/call.h b/src/node/ext/call.h index 340e32682b..45b448e0b1 100644 --- a/src/node/ext/call.h +++ b/src/node/ext/call.h @@ -97,6 +97,7 @@ class Call : public Nan::ObjectWrap { call, this is GRPC_OP_RECV_STATUS_ON_CLIENT and for a server call, this is GRPC_OP_SEND_STATUS_FROM_SERVER */ bool has_final_op_completed; + char *peer; }; class Op { diff --git a/src/node/test/common_test.js b/src/node/test/common_test.js index b7c2c6a8d6..db80207e22 100644 --- a/src/node/test/common_test.js +++ b/src/node/test/common_test.js @@ -100,7 +100,6 @@ describe('Proto message long int serialize and deserialize', function() { var longNumDeserialize = deserializeCls(messages_proto.LongValues, num_options); var serialized = longSerialize({int_64: pos_value}); - console.log(longDeserialize(serialized)); assert.strictEqual(typeof longDeserialize(serialized).int_64, 'string'); /* With the longsAsStrings option disabled, long values are represented as * objects with 3 keys: low, high, and unsigned */ diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js index d2f0511af2..0696e7ae19 100644 --- a/src/node/test/surface_test.js +++ b/src/node/test/surface_test.js @@ -1110,6 +1110,18 @@ describe('Other conditions', function() { done(); }); }); + it('after the call has fully completed', function(done) { + var peer; + var call = client.unary({error: false}, function(err, data) { + assert.ifError(err); + setImmediate(function() { + assert.strictEqual(peer, call.getPeer()); + done(); + }); + }); + peer = call.getPeer(); + assert.strictEqual(typeof peer, 'string'); + }); }); }); describe('Call propagation', function() { @@ -1352,4 +1364,17 @@ describe('Cancelling surface client', function() { }); call.cancel(); }); + it('Should be idempotent', function(done) { + var call = client.div({'divisor': 0, 'dividend': 0}, function(err, resp) { + assert.strictEqual(err.code, surface_client.status.CANCELLED); + // Call asynchronously to try cancelling after call is fully completed + setImmediate(function() { + assert.doesNotThrow(function() { + call.cancel(); + }); + done(); + }); + }); + call.cancel(); + }); }); |