如何在不向Socket写入数据的情况下触发客户端的数据可用信号?——Redis与hiredis异步API环境下EAGAIN错误复现咨询
Got it, let's break down how to modify hiredis's source code to intentionally trigger the "Resource Temporarily Unavailable" (EAGAIN) error on the first write attempt—perfect for validating your custom retry logic without needing to replicate production environment conditions.
Step 1: Locate the SSL Write Handler in hiredis
First, find the ssl.c file in your hiredis source tree. The core function we need to modify is the one handling SSL write operations, typically named redisSslWrite (or redisAsyncSslWrite in some async-focused versions).
Step 2: Add a Per-Connection Flag to Track First Attempt
To avoid interfering with multiple concurrent connections, we'll add a flag to the SSL context struct instead of using a global variable:
- Open
ssl.hand modify theredisSSLContextstruct:
typedef struct redisSSLContext { SSL *ssl; SSL_CTX *ctx; // ... other existing fields ... int first_write_attempt; // New flag: 1 = first write, 0 = subsequent writes } redisSSLContext;
- Find where the
redisSSLContextis initialized (usually inredisSslInitializeor connection setup code) and set the flag to 1:
redisSSLContext *ssl_ctx = redisSslInitialize(...); // Existing initialization if (ssl_ctx != NULL) { ssl_ctx->first_write_attempt = 1; // Initialize flag for first write }
Step 3: Modify the SSL Write Function to Trigger EAGAIN
Jump back to ssl.c and update the write function to return EAGAIN on the first call:
ssize_t redisSslWrite(redisSSLContext *ctx, const void *buf, size_t len) { // Trigger EAGAIN on the first write attempt if (ctx->first_write_attempt) { ctx->first_write_attempt = 0; // Reset flag so subsequent writes behave normally errno = EAGAIN; // Set the error code to simulate resource unavailability return -1; // Return error to trigger hiredis's error handling } // Original hiredis SSL write logic (keep this intact) ssize_t ret = SSL_write(ctx->ssl, buf, len); if (ret <= 0) { int ssl_err = SSL_get_error(ctx->ssl, ret); if (ssl_err == SSL_ERROR_WANT_WRITE || ssl_err == SSL_ERROR_WANT_READ) { errno = EAGAIN; return -1; } // ... existing error handling for fatal SSL errors ... } return ret; }
Step 4: Compile and Test
- Recompile hiredis with your modified source code.
- Link your custom C++ library against this modified hiredis build.
- Run your local tests—your retry logic should now trigger immediately, as the first Redis request will hit the EAGAIN error we forced.
Bonus: Use Conditional Compilation for Cleanup
To avoid leaving this test logic in production code, wrap the EAGAIN trigger with a preprocessor flag:
#ifdef TEST_EAGAIN_TRIGGER if (ctx->first_write_attempt) { ctx->first_write_attempt = 0; errno = EAGAIN; return -1; } #endif
Then compile hiredis with -DTEST_EAGAIN_TRIGGER when you want to run tests, and omit the flag for normal builds.
内容的提问来源于stack exchange,提问作者NindzAI

