hiredis клиент, ошибка redisAsyncFree при разрыве соединения - PullRequest
1 голос
/ 28 февраля 2012

Я пишу клиентское программное обеспечение Redis, используя Hiredis, с асинхронным вводом / выводом. Но он потерпит крах, когда соединение разорвется, и вызов redisAsyncFree.

Основной цикл выглядит так:

RedisTask* theTask;
OSQueueElem* theElem;
redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
printf("New redis context %p\n", c);
redisLibevAttach(EV_DEFAULT_ c);
redisAsyncSetConnectCallback(c,connectCallback);
redisAsyncSetDisconnectCallback(c,disconnectCallback);

while (true)
{
    if (c && c->err == 0)
    {
        theElem = NULL;
        theTask = NULL;
        theElem = fTaskQueue.DeQueue();
        if (theElem != NULL)
            theTask = (RedisTask*)theElem->GetEnclosingObject();
        if (theTask)
        {
            redisAsyncCommand(c, GenericCallback, (void*)theTask, theTask->GetCmd());
        }
        else
            OSThread::Sleep(kMinWaitTimeInMilSecs); // Is this necessary?
        ev_loop(EV_DEFAULT_ EVLOOP_NONBLOCK);
    }
    else
    {
        printf("redis connection broken, reconnect...\n");
        if (c)
        {
            printf("Free redis context %p\n", c);
            redisAsyncFree(c);
        }
        c = redisAsyncConnect("127.0.0.1", 6379);
        redisLibevAttach(EV_DEFAULT_ c);
        redisAsyncSetConnectCallback(c,connectCallback);
        redisAsyncSetDisconnectCallback(c,disconnectCallback);
    }
}

Ошибка возникает при вызове redisAsyncFree. Обратный след выглядит так:

#0  0x00110402 in __kernel_vsyscall ()
#1  0x0026bc00 in raise () from /lib/libc.so.6
#2  0x0026d451 in abort () from /lib/libc.so.6
#3  0x002a121b in __libc_message () from /lib/libc.so.6
#4  0x002ac6fb in free () from /lib/libc.so.6
#5  0x081287fd in _dictClear () at OSRef.h:75
#6  0x0812881d in dictRelease () at OSRef.h:75
#7  0x08129475 in __redisAsyncFree () at OSRef.h:75
#8  0x08129839 in redisAsyncFree () at OSRef.h:75
#9  0x0812d711 in RedisThread::Entry (this=0x8385aa0)

Мне интересно, неверна ли моя логика обработки ошибок. Итак, проблема в том, какова правильная логика для случая, когда c-> err не равен нулю в цикле? Как сделать очистку и переподключиться к серверу?

1 Ответ

1 голос
/ 16 марта 2012

Если это поможет, я написал простой класс для автоматического переподключения.Он не использует асинхронное соединение, но, вероятно, может быть оснащен для него.

class Redis {
        char *host;
        int port;
        public:
        redisContext *c;
        redisReply *r;
        Redis(char* host, int port){
                this->host = host;
                this->port = port;
        }
        void connect(){
                struct timeval timeout = { 1, 500000 };
                if (this->c){
                        redisFree(this->c);
                }
                this->c = redisConnectWithTimeout(this->host, this->port, timeout);
                if (this->c->err){
                        printf("Connection error: %s\n", this->c->errstr);
                        exit(1);
                }
        }
        void cmd(char* r_cmd, int save_reply=0){
                int retry = 0;
                while(true){
                        this->r = (redisReply*)redisCommand(this->c, r_cmd);
                        if (this->r == NULL) {
                                fprintf(stdout, "Retrying to connect to redis...\n");
                                sleep(2);
                                this->connect();
                        } else {
                                if (!save_reply){
                                        freeReplyObject(this->r);
                                }
                                return;
                        }
                        if (retry >= 10){
                                printf("Reply was null! (%s)\n",r_cmd);
                                exit(1);
                        }
                        retry++;
                }
        }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...