fix(lib): a stale OpenSSL error no longer kills a healthy connection (bug-1871)

SSL_get_error() reports SSL_ERROR_SSL whenever the calling thread's
OpenSSL error queue is non-empty. io_worker serves every endpoint from
one thread, so an error left by another connection -- a ctrlstatus
client's EOF queues 'unexpected eof while reading' in OpenSSL 3 -- turned
the next plain would-block SSL_read on a healthy connection into a fatal
error. handle_error() then tore that connection down; mid snapshot
transfer this left a rejoining standby with a truncated snap.part until
its liveness timeout forced a reconnect and a fresh transfer.

Clear the queue before each SSL_read/SSL_write/SSL_do_handshake so the
classification is about that call only.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-09-29 13:59:44 +00:00
parent 3444cf1657
commit 754d5bcf3e
Signed by untrusted user: rshen
GPG key ID: 80533536B0EB651C
4 changed files with 218 additions and 0 deletions

View file

@ -49,6 +49,7 @@ extern void test_netio_arm_failure(void);
extern void test_netio_close_propagation(void);
extern void test_netio_bounded_connect(void);
extern void test_netio_batch_dispatch_uaf(void);
extern void test_netio_err_queue(void);
extern void test_request_send_propagation(void);
extern void test_raft(void);
extern void test_wal_wire(void);
@ -176,6 +177,7 @@ int main(int argc, char* argv[])
TEST(test_netio_close_propagation);
TEST(test_netio_bounded_connect);
TEST(test_netio_batch_dispatch_uaf);
TEST(test_netio_err_queue);
TEST(test_request_send_propagation);
TEST(test_raft);
TEST(test_wal_wire);