Skip to content

h2: client: keep POLLOUT asserted while netconn has pps pending#3613

Closed
saghul wants to merge 3 commits into
warmcat:mainfrom
saghul:fix-h2-client-pollout-pps-flush
Closed

h2: client: keep POLLOUT asserted while netconn has pps pending#3613
saghul wants to merge 3 commits into
warmcat:mainfrom
saghul:fix-h2-client-pollout-pps-flush

Conversation

@saghul

@saghul saghul commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

rops_perform_user_POLLOUT_h2() ends by calling
lws_wsi_mux_action_pending_writeable_reqs(), which decides POLLOUT purely
from child streams' requested_POLLOUT and clears POLLOUT when no child
wants it. It ignores the network connection's own queued protocol sends
(wsi->h2.h2n->pps), e.g. a connection- or stream-level WINDOW_UPDATE that
grants the peer receive-window credit. When such a pps is queued but no
child stream currently wants POLLOUT, POLLOUT is cleared and the pps is
never flushed, so the peer never gets the credit and the transfer stalls.

This is easy to hit on the client with a bodyless request (e.g. a plain
GET): the request stream goes HALF_CLOSED_LOCAL as soon as the headers are
sent with END_STREAM, so no child wants POLLOUT, while the netconn still
needs to emit the WINDOW_UPDATE that opens the receive window. The
response headers arrive but the body stalls at the flow-control window
(the stream window, or 65535 at the connection level) until the peer
resets the stream.

Fix: keep POLLOUT asserted while the netconn still has pps pending, before
falling through to the child-only reconciler.

Observed only with the mbedtls TLS backend; the byte-identical code under
GnuTLS/OpenSSL happens to flush via different read/POLLOUT interleaving,
which is likely why this has gone unnoticed.

pi_ixeL and others added 3 commits June 17, 2026 09:03
Integrate OpenHiTLS as a new TLS backend option for libwebsockets,
providing an alternative to OpenSSL, mbedTLS, and other TLS libraries.

Core changes:
- CMake detection and build configuration for OpenHiTLS
- Complete TLS client and server implementation
- X.509 certificate operations (parse, verify, load)
- Crypto primitives: AES, RSA, EC, Hash operations
- TLS 1.2 and TLS 1.3 support with session management
- SNI, ALPN, and keylog callback support
- BSL_UIO wrapper layer for OpenHiTLS I/O abstraction

Technical details:
- New cmake/FindOpenHITLS.cmake for library detection
- Backend-specific code in lib/tls/openhitls/
- Integration with lws TLS abstraction layer
- Support for both memory and file-based certificates
- Error mapping between OpenHiTLS and lws error codes
rops_perform_user_POLLOUT_h2() ends by calling
lws_wsi_mux_action_pending_writeable_reqs(), which decides POLLOUT purely
from child streams' requested_POLLOUT and clears POLLOUT when no child
wants it.  It ignores the network connection's own queued protocol sends
(wsi->h2.h2n->pps), e.g. a connection- or stream-level WINDOW_UPDATE that
grants the peer receive-window credit.  When such a pps is queued but no
child stream currently wants POLLOUT, POLLOUT is cleared and the pps is
never flushed, so the peer never gets the credit and the transfer stalls.

This is easy to hit on the client with a bodyless request (e.g. a plain
GET): the request stream goes HALF_CLOSED_LOCAL as soon as the headers are
sent with END_STREAM, so no child wants POLLOUT, while the netconn still
needs to emit the WINDOW_UPDATE that opens the receive window.  The
response headers arrive but the body stalls at the flow-control window
(the stream window, or 65535 at the connection level) until the peer
resets the stream.

Fix: keep POLLOUT asserted while the netconn still has pps pending, before
falling through to the child-only reconciler.

Observed only with the mbedtls TLS backend; the byte-identical code under
GnuTLS/OpenSSL happens to flush via different read/POLLOUT interleaving,
which is likely why this has gone unnoticed.
@lws-team lws-team force-pushed the main branch 2 times, most recently from 04492e6 to d8b4769 Compare June 17, 2026 11:30
@lws-team

Copy link
Copy Markdown
Member

Thanks I extracted just the patch and added it to main.

@lws-team lws-team closed this Jun 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants