Fix a list management bug exposed by new locking scheme in client_channel

pull/2303/head
Craig Tiller 10 years ago
parent 2a6e356779
commit 17be5dc796
  1. 8
      src/core/transport/chttp2/internal.h
  2. 18
      src/core/transport/chttp2/stream_lists.c
  3. 10
      src/core/transport/chttp2_transport.c

@ -63,6 +63,7 @@ typedef enum {
GRPC_CHTTP2_LIST_WRITABLE_WINDOW_UPDATE, GRPC_CHTTP2_LIST_WRITABLE_WINDOW_UPDATE,
GRPC_CHTTP2_LIST_PARSING_SEEN, GRPC_CHTTP2_LIST_PARSING_SEEN,
GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING, GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING,
GRPC_CHTTP2_LIST_CANCELLED_WAITING_FOR_WRITING,
GRPC_CHTTP2_LIST_INCOMING_WINDOW_UPDATED, GRPC_CHTTP2_LIST_INCOMING_WINDOW_UPDATED,
/** streams that are waiting to start because there are too many concurrent /** streams that are waiting to start because there are too many concurrent
streams on the connection */ streams on the connection */
@ -526,6 +527,13 @@ int grpc_chttp2_list_pop_closed_waiting_for_parsing(
grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global **stream_global); grpc_chttp2_stream_global **stream_global);
void grpc_chttp2_list_add_cancelled_waiting_for_writing(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
int grpc_chttp2_list_pop_cancelled_waiting_for_writing(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global **stream_global);
void grpc_chttp2_list_add_read_write_state_changed( void grpc_chttp2_list_add_read_write_state_changed(
grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global); grpc_chttp2_stream_global *stream_global);

@ -282,6 +282,24 @@ int grpc_chttp2_list_pop_closed_waiting_for_parsing(
return r; return r;
} }
void grpc_chttp2_list_add_cancelled_waiting_for_writing(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global),
GRPC_CHTTP2_LIST_CANCELLED_WAITING_FOR_WRITING);
}
int grpc_chttp2_list_pop_cancelled_waiting_for_writing(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global **stream_global) {
grpc_chttp2_stream *stream;
int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream,
GRPC_CHTTP2_LIST_CANCELLED_WAITING_FOR_WRITING);
*stream_global = &stream->global;
return r;
}
void grpc_chttp2_list_add_incoming_window_updated( void grpc_chttp2_list_add_incoming_window_updated(
grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) { grpc_chttp2_stream_global *stream_global) {

@ -765,9 +765,18 @@ static void unlock_check_read_write_state(grpc_chttp2_transport *t) {
} }
} }
if (!t->writing_active) {
while (grpc_chttp2_list_pop_cancelled_waiting_for_writing(transport_global, &stream_global)) {
grpc_chttp2_list_add_read_write_state_changed(transport_global, stream_global);
}
}
while (grpc_chttp2_list_pop_read_write_state_changed(transport_global, while (grpc_chttp2_list_pop_read_write_state_changed(transport_global,
&stream_global)) { &stream_global)) {
if (stream_global->cancelled) { if (stream_global->cancelled) {
if (t->writing_active && stream_global->write_state != GRPC_WRITE_STATE_SENT_CLOSE) {
grpc_chttp2_list_add_cancelled_waiting_for_writing(transport_global, stream_global);
} else {
stream_global->write_state = GRPC_WRITE_STATE_SENT_CLOSE; stream_global->write_state = GRPC_WRITE_STATE_SENT_CLOSE;
stream_global->read_closed = 1; stream_global->read_closed = 1;
if (!stream_global->published_cancelled) { if (!stream_global->published_cancelled) {
@ -782,6 +791,7 @@ static void unlock_check_read_write_state(grpc_chttp2_transport *t) {
stream_global->published_cancelled = 1; stream_global->published_cancelled = 1;
} }
} }
}
if (stream_global->write_state == GRPC_WRITE_STATE_SENT_CLOSE && if (stream_global->write_state == GRPC_WRITE_STATE_SENT_CLOSE &&
stream_global->read_closed && stream_global->in_stream_map) { stream_global->read_closed && stream_global->in_stream_map) {
if (t->parsing_active) { if (t->parsing_active) {

Loading…
Cancel
Save