Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions changes-entries/h3_blocked_stream_spin.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*) mod_http3: Fixed an event-thread spin while a client holds its
flow-control window shut: a blocked stream is now blocked again each time
nghttp3 offers it.
[Alexander Gerasimov <codeguard gmail.com>]
4 changes: 4 additions & 0 deletions changes-entries/h3_drain_pending_handshakes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*) mod_http3: Fixed a graceful restart that never ended: a handshake still
pending when the child started to drain did not finish or time out, so
the old child kept its connection count and the port.
[Alexander Gerasimov <codeguard gmail.com>]
3 changes: 3 additions & 0 deletions changes-entries/h3_session_allocator_race.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*) mod_http3: Fixed a heap race that crashed the child: worker threads and
the event thread allocated from one session allocator that had no mutex.
[Alexander Gerasimov <codeguard gmail.com>]
9 changes: 9 additions & 0 deletions modules/http3/h3_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,15 @@ static apr_status_t spawn_serviced_session(h3_io_t* io, h3q_conn* conn)
}
apr_allocator_owner_set(allocator, session_pool);
apr_pool_tag(session_pool, "h3_session");
/* Workers allocate from stream subpools while this thread makes its own: share the allocator safely. */
apr_thread_mutex_t* alloc_mutex = NULL;
if (apr_thread_mutex_create(&alloc_mutex, APR_THREAD_MUTEX_DEFAULT, session_pool) != APR_SUCCESS)
{
apr_pool_destroy(session_pool);
h3q_conn_free(conn);
return APR_EGENERAL;
}
apr_allocator_mutex_set(allocator, alloc_mutex);

h3_session* session = NULL;
if (h3_session_create(&session, io->server, conn, session_pool) != APR_SUCCESS)
Expand Down
5 changes: 3 additions & 2 deletions modules/http3/h3_stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,14 @@ void flush_nghttp3(h3_session* session)
nghttp3_conn_add_ack_offset(session->ngh3, sid, res.accepted);
if (res.blocked)
{
/* Send buffer full: skip this stream instead of busy-looping on the same vec. */
/* Send buffer full: skip this stream instead of busy-looping on the same vec.
* Block it again every time: resume_stream reschedules a blocked stream. */
if (!h3s->write_blocked)
{
h3s->write_blocked = 1;
session->blocked_streams++;
nghttp3_conn_block_stream(session->ngh3, sid);
}
nghttp3_conn_block_stream(session->ngh3, sid);
continue;
}
}
Expand Down
4 changes: 4 additions & 0 deletions modules/http3/h3_threads.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ void* APR_THREAD_FUNC h3_event_thread(apr_thread_t* thread, void* data)
h3q_conn_free(conn);
}
}
}
if (io->thread_running)
{
/* Also while draining: a pending handshake counts as an MPM connection, so it must finish or time out. */
progress_pending_handshakes(io);
}

Expand Down