Skip to content
Snippets Groups Projects
Commit c7cde233 authored by Michael Lumish's avatar Michael Lumish Committed by GitHub
Browse files

Merge pull request #11141 from murgatroid99/node_write_after_end_race_fix

Fix race between destroying call after status and handling write failure
parents 42d858a9 d822e2f5
No related branches found
No related tags found
No related merge requests found
...@@ -721,6 +721,14 @@ NAN_METHOD(Call::StartBatch) { ...@@ -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) { ...@@ -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. */
setImmediate(callback);
}
try { try {
message = this.serialize(chunk); message = this.serialize(chunk);
} catch (e) { } catch (e) {
...@@ -119,8 +125,10 @@ function _write(chunk, encoding, callback) { ...@@ -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();
}); });
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment