mod_http3: Keep the child's threads off the child pool (#940)

* mod_http3: Keep the child's threads off the child pool

The threads of mod_http3 allocated from the child pool, which is not
thread-safe, and kept running while it was destroyed:

- The port acquirer thread, in every child that does not own the UDP
  port, created a socket in the child pool every 200 ms, racing with the
  main thread and never freeing it.
- Under prefork the child pool's allocator has no mutex and is shared
  with the request pools, which the event thread raced with when it
  created connection pools.
- prefork does not run the child_stopping hook when a child exits from
  a signal handler, so neither thread was stopped before the child pool
  was destroyed and exit() ran OpenSSL's cleanup under them.

These crashed children with SIGSEGV on stop, mostly under prefork.

Give mod_http3 a pool of its own with a locked allocator, give each port
acquisition attempt a scratch pool that is cleared on retry, and stop the
threads from a pre-cleanup of the child pool as well.

Generated-by: Claude Code (Claude Opus 5.5)

* mod_http3: Move the thread-safe pool helper to h3_threads

Review feedback: keep the body of stop_child_threads() in
h3_c1_child_stopping(), which the child pool cleanup now calls, so no
forward declaration is needed. Move the pool creation to h3_threads.c so
other code can reuse it.

* modules/http3/h3_server.c (h3_c1_child_stopping): Fold in
  stop_child_threads().
* modules/http3/h3_threads.c, modules/http3/include/h3_threads.h
  (h3_thread_safe_pool_create): New, from create_h3_pool() in h3_server.c.

Generated-by: Claude Code (Claude Opus 5.5)

* mod_http3: Do not allocate from the HTTP/3 pool from two threads

Review feedback: the mutex on the allocator of the HTTP/3 pool covers
subpools, not allocations from the pool itself. h3_io_listen_start()
registered its pool cleanup after starting the event thread, which
allocates from the same pool, so the two could allocate at once when
the port acquirer thread started listening. Register it first.

Also destroy the pool when its mutex cannot be created, log when the
port acquirer cannot create its pool, drop an empty APLOGNO() that no
other message in the file has, and keep the declarations in
h3_child_init() at the top of their blocks, as C89 requires.

* modules/http3/h3_io.c (h3_io_listen_start): Register the cleanup
  before starting the event thread.
* modules/http3/h3_server.c (port_acquire_thread_fn): Log the pool
  creation failure.
  (h3_child_init): Declare variables first; drop the APLOGNO().
* modules/http3/h3_threads.c (h3_thread_safe_pool_create): Destroy the
  pool if its mutex cannot be created.
* modules/http3/include/h3_threads.h: Say what the mutex does not cover.

Generated-by: Claude Code (Claude Opus 5.5)
4 files changed