- Notifications
You must be signed in to change notification settings - Fork 24.3k
Closed
Closed
Copy link
Description
In short, I believe the issue is early release of a blocked client which keeps on sending data from a worker thread.
To reproduce, compile and load the module below, call crash.ASYNC
#define REDISMODULE_EXPERIMENTAL_API // Required for block client. #include "redismodule.h" #include <pthread.h> #include <unistd.h> #define UNUSED(x) (void)(x) void* _Crash_ASync(void *args) { RedisModuleBlockedClient *bc = (RedisModuleBlockedClient*)args; RedisModuleCtx *ctx = RedisModule_GetThreadSafeContext(bc); RedisModule_ReplyWithArray(ctx, 999999); for(int i = 0; i < 999999; i++) { RedisModule_ReplyWithSimpleString(ctx, "Oh no!"); } RedisModule_FreeThreadSafeContext(ctx); RedisModule_UnblockClient(bc, NULL); return NULL; } int Crash_ASync(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { /* When output buffer overflows, Redis crashs when disconnect the client. */ UNUSED(argv); UNUSED(argc); RedisModuleBlockedClient *bc = RedisModule_BlockClient(ctx, NULL, NULL, NULL, 0); pthread_t thread; pthread_create(&thread, NULL, _Crash_ASync, bc); pthread_detach(thread); return REDISMODULE_OK; } int Crash_Sync(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { /* When output buffer overflows, Redis is able to * disconnect the client. */ UNUSED(argv); UNUSED(argc); RedisModule_ReplyWithArray(ctx, 999999); for(int i = 0; i < 999999; i++) { RedisModule_ReplyWithSimpleString(ctx, "No worries!"); } return REDISMODULE_OK; } void usage() { printf("\n\n\n***************************************************************************\n"); printf("This module triggers a bug caused by an early client free of a blocked-client while still sending data from a thread safe context\n"); printf("Be sure to reduce client output buffer limit by:\n"); printf("CONFIG SET client-output-buffer-limit \"normal 1 1 1 slave 1 1 1 pubsub 1 1 1\"\n"); printf("***************************************************************************\n\n\n"); } int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { UNUSED(argv); UNUSED(argc); if (RedisModule_Init(ctx, "crash", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR) { return REDISMODULE_ERR; } // Trigger crash. if(RedisModule_CreateCommand(ctx, "crash.ASYNC", Crash_ASync, "write", 1, 1, 1) == REDISMODULE_ERR) { return REDISMODULE_ERR; } // Won't trigger the crash. if(RedisModule_CreateCommand(ctx, "crash.SYNC", Crash_Sync, "write", 1, 1, 1) == REDISMODULE_ERR) { return REDISMODULE_ERR; } usage(); return REDISMODULE_OK; } Metadata
Metadata
Assignees
Labels
No labels