/* * test_request_send_propagation.c — bug-650: xce_request() must PROPAGATE an * endpoint_enq() send failure, not swallow it. * * xce_request() (and the other request.c senders) ignored endpoint_enq()'s * return and always returned 0. So when the transport was dead — endpoint_enq() * returns <0 and marks the endpoint dead (bug-646) — xce_request() still * reported success. xce_jobsubmit() then fell through to a BLOCKING cbuf_get() * and hung forever waiting for a reply to a request that was never transmitted * (server idle, client fd unconnected). xce_request() must return the negative * enq error so the failover loop rotates instead of blocking. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include "netio.h" #include "request.h" /* * A request that ENCODES successfully but whose send fails because the endpoint * is dead (EPOLL_CTL_MOD on an fd that is not registered → ENOENT) must make * xce_request() return a negative error, not 0. */ static void test_xce_request_propagates_send_failure(void) { iomgr_t iomgr; memset(&iomgr, 0, sizeof(iomgr)); TEST_ASSERT_EQUAL_INT(0, iomgr_init(&iomgr)); endpoint_t *ep = endpoint_get(); TEST_ASSERT_NOT_NULL(ep); ep->fd = socket(AF_INET, SOCK_STREAM, 0); /* valid fd, NOT in the epoll */ TEST_ASSERT_TRUE(ep->fd >= 0); ep->iomgr = &iomgr; ep->ssl_handshake_done = 1; ep->flags = 0; /* force iomgr_update_poll MOD on the unregistered fd */ char nm[] = "tester"; char ky[] = "key"; xce_peerinfo_t peer = { .name = nm, .key = ky }; ep->peer = &peer; xce_request_t req; memset(&req, 0, sizeof(req)); req.opcode = OPCode_nop; req.seq = 42; int rc = xce_request(ep, &req); /* Old code: always 0 (swallowed). Fixed: the negative enq error propagates. */ TEST_ASSERT_TRUE(rc < 0); endpoint_fini(ep); free(ep); close(iomgr.epoll_fd); printf("test_xce_request_propagates_send_failure: PASS\n"); } void test_request_send_propagation(void) { printf("\n>> request send-failure propagation tests\n\n"); RUN_TEST(test_xce_request_propagates_send_failure); }