I began to interface my program with redis but It randomly crash. So at first, I retailed a place in hell for me, calling all the saints. But than I began to suspect about the scope and the life of the variables. This because each crash was caused from a variable passed as argument in the command function (ctx, argv), and than forwarded to relative thread function.
It happend several times, that the crash was caused from the very first call to openkey() in the function tb.tree(). So from the load until I called this function I did not allocate anything unless an hashtable, that is extensively tested and a parser, it is not mine, but I began to trust him since I ever worked with him.
Other times the crash was caused from getclientid(ctx), also passed as argument from the command function to the thread function.
Since to adapt my program to this schema I have to do a lot of job, I would ask you first, if the ctx, and argv[] get destroyed when leave the command function, and I have to create my own copy. ```
void * tb_tree_command_thd(void arg) { sd.lock_all_requests=1; sd.nclients_loggeds++; void targ = arg; RedisModuleBlockedClient bc = targ[0]; Rms key_name =targ[1]; Ctx ctx =targ[2]; free(targ); ///IT CRASHES HERE. And until here I did not do anything
RedisModuleKey *key = RedisModule_OpenKey(ctx,key_name,REDISMODULE_READ|REDISMODULE_WRITE);
int type = RedisModule_KeyType(key);
if (type != REDISMODULE_KEYTYPE_EMPTY && type != REDISMODULE_KEYTYPE_STRING)
{
RedisModule_ReplyWithError(ctx,REDISMODULE_ERRORMSG_WRONGTYPE);
goto ESCAPE;
}
. . . //does continue }
int tb_tree_command(Ctx* ctx,Rms ** argv,int argc) { if (sd.lock_all_requests)return RedisModule_ReplyWithError(ctx,"ERR Server Cannot accept requests."); if (argc != 2) return RedisModule_WrongArity(ctx); if (sd.tb) return RedisModule_ReplyWithError(ctx,"ERR TreeBase already loaded.");
pthread_t tid;
RedisModuleBlockedClient *bc = RedisModule_BlockClient
(ctx,tb_redis_showcur_thd,tb_redis_load_Timeout,tb_redis_free_private_data,sd.timeout);
void **targ = malloc(sizeof(void*)*3);
targ[0] = bc;
targ[1] = argv[1]; //RedisModule_CreateStringFromString( ctx,);
targ[2] =ctx;
if (pthread_create(&tid,NULL,tb_tree_command_thd,targ) != 0) {
RedisModule_AbortBlock(bc);
RedisModule_FreeString(ctx,targ[1]);
free(targ);
return RedisModule_ReplyWithError(ctx,"-ERR Can't start thread");
}
return REDISMODULE_OK;
} int RedisModule_OnLoad(RedisModuleCtx ctx, RedisModuleString *argv, int argc) { REDISMODULE_NOT_USED(argv); REDISMODULE_NOT_USED(argc);
if (RedisModule_Init(ctx,"tb",1,REDISMODULE_APIVER_1)
== REDISMODULE_ERR) return REDISMODULE_ERR;/*
TB_type = RedisModule_CreateDataType(ctx,"tb_type",0, tbRdbLoad, tbRdbSave, tbRAofRewrite, tbRDigest, tbRFree); if (TB_type== NULL) return REDISMODULE_ERR; */ if (RedisModule_CreateCommand(ctx,"tb.cmd", tb_rc,"write deny-oom",1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; if (RedisModule_CreateCommand(ctx,"tb.show", tb_show,"readonly",1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; if (RedisModule_CreateCommand(ctx,"tb.tree", tb_tree_command,"write deny-oom",1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; if (RedisModule_CreateCommand(ctx,"tb.unload", tb_unload_command,"readonly",1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; if (RedisModule_CreateCommand(ctx,"tb.insert", tb_insert_command,"write deny-oom",1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; sd.pars=init_parser(); if (!sd.pars) return REDISMODULE_ERR; sd.ClientInterface=hCreator(100); if (!sd.ClientInterface) return REDISMODULE_ERR; //if (!(sd.stk=new_stack(10,NULL)) )return REDISMODULE_ERR; sd.timeout=TBDEFAULTTIMEOUT; sd.lock_all_requests=0; sd.nclients_loggeds=0; sd.tb=NULL; return REDISMODULE_OK; }
UPDATE I pasted the already modified one. But also it cannot continue since without ctx cannot open the key
Comment From: itamarhaber
The call's context and arguments aren't thread-safe so you can't use them in your worker thread. You can copy and send the values of relevant args when you start the thread but the ctx will be available again only in the reply callback.
Comment From: itamarhaber
Closing