diff options
author | Craig Tiller <ctiller@google.com> | 2015-08-07 10:40:33 -0700 |
---|---|---|
committer | Craig Tiller <ctiller@google.com> | 2015-08-07 10:40:33 -0700 |
commit | 2e95e4ac1dcbe38555ab2c0307d98654c2677346 (patch) | |
tree | bba103013850dc651304961d5c8d71a8469f51f6 /src/core | |
parent | 03b19118e349ca480f2739ed6efd00ba7be4cf45 (diff) |
Move parent removal from final destruction to destruction request
We don't need the list for cancel propagation after that point, and
doing it early avoids a bug whereby the call is reffed after reaching a
zero ref when the parent is destroyed first.
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/surface/call.c | 30 |
1 files changed, 16 insertions, 14 deletions
diff --git a/src/core/surface/call.c b/src/core/surface/call.c index d3e66e9c4c..6e566e6a8f 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -456,20 +456,6 @@ void grpc_call_internal_ref(grpc_call *c) { static void destroy_call(void *call, int ignored_success) { size_t i; grpc_call *c = call; - grpc_call *parent = c->parent; - if (parent) { - gpr_mu_lock(&parent->mu); - if (call == parent->first_child) { - parent->first_child = c->sibling_next; - if (c == parent->first_child) { - parent->first_child = NULL; - } - c->sibling_prev->sibling_next = c->sibling_next; - c->sibling_next->sibling_prev = c->sibling_prev; - } - gpr_mu_unlock(&parent->mu); - GRPC_CALL_INTERNAL_UNREF(parent, "child", 1); - } grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c)); GRPC_CHANNEL_INTERNAL_UNREF(c->channel, "call"); gpr_mu_destroy(&c->mu); @@ -1257,6 +1243,22 @@ grpc_call_error grpc_call_start_ioreq_and_call_back( void grpc_call_destroy(grpc_call *c) { int cancel; + grpc_call *parent = c->parent; + + if (parent) { + gpr_mu_lock(&parent->mu); + if (c == parent->first_child) { + parent->first_child = c->sibling_next; + if (c == parent->first_child) { + parent->first_child = NULL; + } + c->sibling_prev->sibling_next = c->sibling_next; + c->sibling_next->sibling_prev = c->sibling_prev; + } + gpr_mu_unlock(&parent->mu); + GRPC_CALL_INTERNAL_UNREF(parent, "child", 1); + } + lock(c); GPR_ASSERT(!c->destroy_called); c->destroy_called = 1; |