fix(libxce-failover): classify and propagate netio I/O errors on failover
Add io_classify_io_error and propagate endpoint/epoll errors through endpoint_update_epoll and cbuf_get instead of swallowing them, so client failover surfaces the real error rather than hanging. Adds netio arm-failure, close-propagation, and request send-propagation tests. Pre-existing uncommitted work, committed to establish a clean baseline before ha-commit-durability implementation.
This commit is contained in:
parent
749e194207
commit
80bb1d766e
7 changed files with 347 additions and 41 deletions
77
src/lib/testsuite/test_netio_close_propagation.c
Normal file
77
src/lib/testsuite/test_netio_close_propagation.c
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* test_netio_close_propagation.c — bug-648: a peer close/EOF must propagate as a
|
||||
* negative error, never as rc==0.
|
||||
*
|
||||
* io_fsm_do() moved the read FSM to FSM_STATE_ERROR on a peer close but returned
|
||||
* rc = -errno, which on a clean EOF (errno==0) is 0. handle_input() then read
|
||||
* rc>=0, never called handle_error, and a blocked cbuf_get() reply-waiter was
|
||||
* never woken. io_classify_io_error() is the extracted, pure decision; it must
|
||||
* return <0 for every close/error case and 0 only for retriable would-block.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <unity/unity.h>
|
||||
|
||||
/* Pure classifier defined (non-static) in netio.c, linked into this binary. */
|
||||
extern int io_classify_io_error(int ssl_err, int ecode, int io_rc);
|
||||
|
||||
/* WANT_READ / WANT_WRITE are retriable would-block → rc==0, FSM stays put. */
|
||||
static void test_wantread_writeready_is_retriable_zero(void)
|
||||
{
|
||||
TEST_ASSERT_EQUAL_INT(0, io_classify_io_error(SSL_ERROR_WANT_READ, 0, -1));
|
||||
TEST_ASSERT_EQUAL_INT(0, io_classify_io_error(SSL_ERROR_WANT_WRITE, 0, -1));
|
||||
printf("test_wantread_writeready_is_retriable_zero: PASS\n");
|
||||
}
|
||||
|
||||
/* Non-blocking EAGAIN/EWOULDBLOCK syscall (io_rc<0) is retriable → rc==0. */
|
||||
static void test_syscall_eagain_is_retriable_zero(void)
|
||||
{
|
||||
TEST_ASSERT_EQUAL_INT(0, io_classify_io_error(SSL_ERROR_SYSCALL, EAGAIN, -1));
|
||||
TEST_ASSERT_EQUAL_INT(0,
|
||||
io_classify_io_error(SSL_ERROR_SYSCALL, EWOULDBLOCK, -1));
|
||||
printf("test_syscall_eagain_is_retriable_zero: PASS\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* THE BUG: a clean EOF — SSL_read returns 0 with errno==0 — must yield a
|
||||
* NEGATIVE error (not 0) so the close propagates and the waiter is woken.
|
||||
*/
|
||||
static void test_clean_eof_is_negative_not_zero(void)
|
||||
{
|
||||
int rc = io_classify_io_error(SSL_ERROR_SYSCALL, 0 /*errno*/, 0 /*io_rc EOF*/);
|
||||
TEST_ASSERT_TRUE(rc < 0);
|
||||
TEST_ASSERT_EQUAL_INT(-ECONNRESET, rc);
|
||||
printf("test_clean_eof_is_negative_not_zero: PASS\n");
|
||||
}
|
||||
|
||||
/* Clean TLS close_notify (ZERO_RETURN) with errno==0 must also be negative. */
|
||||
static void test_zero_return_is_negative_not_zero(void)
|
||||
{
|
||||
int rc = io_classify_io_error(SSL_ERROR_ZERO_RETURN, 0, 0);
|
||||
TEST_ASSERT_TRUE(rc < 0);
|
||||
TEST_ASSERT_EQUAL_INT(-ECONNRESET, rc);
|
||||
printf("test_zero_return_is_negative_not_zero: PASS\n");
|
||||
}
|
||||
|
||||
/* A hard syscall error preserves its real errno (still negative). */
|
||||
static void test_hard_syscall_error_preserves_errno(void)
|
||||
{
|
||||
TEST_ASSERT_EQUAL_INT(-ECONNRESET,
|
||||
io_classify_io_error(SSL_ERROR_SYSCALL, ECONNRESET, -1));
|
||||
printf("test_hard_syscall_error_preserves_errno: PASS\n");
|
||||
}
|
||||
|
||||
void test_netio_close_propagation(void)
|
||||
{
|
||||
printf("\n>> netio peer-close propagation tests\n\n");
|
||||
|
||||
RUN_TEST(test_wantread_writeready_is_retriable_zero);
|
||||
RUN_TEST(test_syscall_eagain_is_retriable_zero);
|
||||
RUN_TEST(test_clean_eof_is_negative_not_zero);
|
||||
RUN_TEST(test_zero_return_is_negative_not_zero);
|
||||
RUN_TEST(test_hard_syscall_error_preserves_errno);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue