Merge pull request #322 from ctiller/http

Prevent a potential deadlock
pull/388/head
Nicolas Noble 10 years ago
commit 4a92bc3c69
  1. 28
      src/core/transport/chttp2_transport.c

@ -237,6 +237,9 @@ struct transport {
/* state for a stream that's not yet been created */
grpc_stream_op_buffer new_stream_sopb;
/* stream ops that need to be destroyed, but outside of the lock */
grpc_stream_op_buffer nuke_later_sopb;
/* active parser */
void *parser_data;
stream *incoming_stream;
@ -370,6 +373,8 @@ static void unref_transport(transport *t) {
}
gpr_free(t->pending_goaways);
grpc_sopb_destroy(&t->nuke_later_sopb);
gpr_free(t);
}
@ -416,6 +421,7 @@ static void init_transport(transport *t, grpc_transport_setup_callback setup,
t->cap_pending_goaways = 0;
gpr_slice_buffer_init(&t->outbuf);
gpr_slice_buffer_init(&t->qbuf);
grpc_sopb_init(&t->nuke_later_sopb);
if (is_client) {
gpr_slice_buffer_add(&t->qbuf,
gpr_slice_from_copied_string(CLIENT_CONNECT_STRING));
@ -555,6 +561,11 @@ static int init_stream(grpc_transport *gt, grpc_stream *gs,
return 0;
}
static void schedule_nuke_sopb(transport *t, grpc_stream_op_buffer *sopb) {
grpc_sopb_append(&t->nuke_later_sopb, sopb->ops, sopb->nops);
sopb->nops = 0;
}
static void destroy_stream(grpc_transport *gt, grpc_stream *gs) {
transport *t = (transport *)gt;
stream *s = (stream *)gs;
@ -681,6 +692,11 @@ static void unlock(transport *t) {
int i;
pending_goaway *goaways = NULL;
grpc_endpoint *ep = t->ep;
grpc_stream_op_buffer nuke_now = t->nuke_later_sopb;
if (nuke_now.nops) {
memset(&t->nuke_later_sopb, 0, sizeof(t->nuke_later_sopb));
}
/* see if we need to trigger a write - and if so, get the data ready */
if (ep && !t->writing) {
@ -750,6 +766,10 @@ static void unlock(transport *t) {
unref_transport(t);
}
if (nuke_now.nops) {
grpc_sopb_destroy(&nuke_now);
}
gpr_free(goaways);
}
@ -1006,9 +1026,9 @@ static void cancel_stream_inner(transport *t, stream *s, gpr_uint32 id,
if (s) {
/* clear out any unreported input & output: nobody cares anymore */
grpc_sopb_reset(&s->parser.incoming_sopb);
had_outgoing = s->outgoing_sopb.nops != 0;
grpc_sopb_reset(&s->outgoing_sopb);
schedule_nuke_sopb(t, &s->parser.incoming_sopb);
schedule_nuke_sopb(t, &s->outgoing_sopb);
if (s->cancelled) {
send_rst = 0;
} else if (!s->read_closed || !s->sent_write_closed || had_outgoing) {
@ -1739,8 +1759,8 @@ static void add_to_pollset(grpc_transport *gt, grpc_pollset *pollset) {
static const grpc_transport_vtable vtable = {
sizeof(stream), init_stream, send_batch, set_allow_window_updates,
add_to_pollset, destroy_stream, abort_stream, goaway,
close_transport, send_ping, destroy_transport};
add_to_pollset, destroy_stream, abort_stream, goaway, close_transport,
send_ping, destroy_transport};
void grpc_create_chttp2_transport(grpc_transport_setup_callback setup,
void *arg,

Loading…
Cancel
Save