2012-02-28 57 views
0

我正在用異步I/O使用hiredis編寫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

您是否嘗試調用redisAsyncDisconnect?我不會在c-> err上使用測試來檢測斷開連接,而是在斷開連接回調中執行此操作。 – 2012-02-28 10:36:36

回答

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++; 
       } 
     } 
}; 
相關問題