2012-02-28 2 views
0

hiredis를 사용하여 async I/O를 사용하여 redis 클라이언트 소프트웨어를 작성하고 있습니다. 하지만 연결이 끊어지면 충돌이 발생하고 redisAsyncFree가 호출됩니다.hiredis 클라이언트, 연결이 끊어진 경우 redisAsyncFree 오류

메인 루프는 다음과 같이이다 : 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); 
    } 
} 

오류가 발생합니다. 역 추적은 다음과 같습니다.

#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이 루프에서 0이 아닌 경우의 올바른 논리는 무엇입니까? 서버를 정리하고 다시 연결하는 방법은 무엇입니까?

+0

대신 redisAsyncDisconnect를 호출하려고 했습니까? 나는 끊어진 연결을 감지하기 위해 c-> err에 대한 테스트를 사용하지 않고, 연결 해제 콜백에서 그것을 수행한다. –

답변

0

도움이된다면 자동 재 연결을 처리 할 수있는 간단한 클래스를 작성했습니다. 비동기 연결을 사용하지는 않지만 비동기 연결을 사용할 수 있습니다.

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++; 
       } 
     } 
}; 
관련 문제