mirror of https://github.com/grpc/grpc-node.git
Fix race between destroying call after status and handling write failure
This commit is contained in:
parent
c604bbeeac
commit
9538b3d5a9
|
|
@ -721,6 +721,14 @@ NAN_METHOD(Call::StartBatch) {
|
||||||
}
|
}
|
||||||
Local<Function> callback_func = info[1].As<Function>();
|
Local<Function> callback_func = info[1].As<Function>();
|
||||||
Call *call = ObjectWrap::Unwrap<Call>(info.This());
|
Call *call = ObjectWrap::Unwrap<Call>(info.This());
|
||||||
|
if (call->wrapped_call == NULL) {
|
||||||
|
/* This implies that the call has completed and has been destroyed. To emulate
|
||||||
|
* previous behavior, we should call the callback immediately with an error,
|
||||||
|
* as though the batch had failed in core */
|
||||||
|
Local<Value> argv[] = {Nan::Error("The async function failed because the call has completed")};
|
||||||
|
Nan::Call(callback_func, Nan::New<Object>(), 1, argv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
Local<Object> obj = Nan::To<Object>(info[0]).ToLocalChecked();
|
Local<Object> obj = Nan::To<Object>(info[0]).ToLocalChecked();
|
||||||
Local<Array> keys = Nan::GetOwnPropertyNames(obj).ToLocalChecked();
|
Local<Array> keys = Nan::GetOwnPropertyNames(obj).ToLocalChecked();
|
||||||
size_t nops = keys->Length();
|
size_t nops = keys->Length();
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,12 @@ function _write(chunk, encoding, callback) {
|
||||||
/* jshint validthis: true */
|
/* jshint validthis: true */
|
||||||
var batch = {};
|
var batch = {};
|
||||||
var message;
|
var message;
|
||||||
|
var self = this;
|
||||||
|
if (this.writeFailed) {
|
||||||
|
/* Once a write fails, just call the callback immediately to let the caller
|
||||||
|
flush any pending writes. */
|
||||||
|
callback();
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
message = this.serialize(chunk);
|
message = this.serialize(chunk);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -119,8 +125,10 @@ function _write(chunk, encoding, callback) {
|
||||||
batch[grpc.opType.SEND_MESSAGE] = message;
|
batch[grpc.opType.SEND_MESSAGE] = message;
|
||||||
this.call.startBatch(batch, function(err, event) {
|
this.call.startBatch(batch, function(err, event) {
|
||||||
if (err) {
|
if (err) {
|
||||||
// Something has gone wrong. Stop writing by failing to call callback
|
/* Assume that the call is complete and that writing failed because a
|
||||||
return;
|
status was received. In that case, set a flag to discard all future
|
||||||
|
writes */
|
||||||
|
self.writeFailed = true;
|
||||||
}
|
}
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue