windows xp下redis客戶端無法連接服務端(MicrosoftArchive/redis邏輯bug)

PR:https://github.com/MicrosoftArchive/redis/pull/598


錯誤描述與處理辦法

用redis-cli連接服務端時六敬,錯誤提示好像是Could not connect to Redis at xxx:poll(2)瑟俭,事實上使用微軟的redis on windows編譯的Win32_Interop庫在window版本低于6.0時都不能連接上redis server肮街。

先說結(jié)論吧沉眶,造成bug的原因是低版本時調(diào)用select函數(shù)前多進行了一次rfd(redis的文件描述符)與socket的映射保礼,解決方案是

  1. 把Win32_FDAPI.cpp的1005~1019行刪除(FDAPI_select函數(shù)的三個if代碼塊)揖盘;
  2. 674行的fds[i].fd == INVALID_SOCKET改為pollCopy[i].fd == INVALID_SOCKET言蛇;
  3. 677行的if (pollCopy[i].fd >= FD_SETSIZE)改為if (fds[i].fd >= FD_SETSIZE),或者直接刪除677~680行珊泳;
  4. 重新編譯Win32_Interop鲁冯,hiredis和RedisCli即可。

順便一提我在使用xp工具集編譯時出現(xiàn)了一個問題色查,WS2tcpip.h的第48~51行的預處理并沒有起作用薯演,無法包含winapifamily.h,于是我把它直接改為了#include "win32_winapifamily.h"秧了。


問題分析

先來看一下相關(guān)部分的源碼:


FDAPI_poll函數(shù)
FDAPI_poll函數(shù)跨扮,注意667到680行的合法性檢查.png
原FDAPI_select函數(shù)
  • 在635行,F(xiàn)DAPI_poll函數(shù)進行了一次RFD到socket的映射验毡,此時pollCopy[n].fd已經(jīng)是socket句柄并在682~684行復制到fd_set中衡创,當WindowsVersion低于6.0時作為WSAPoll的替代,在688行FDAPI_poll調(diào)用了FDAPI_select晶通;
  • 但在FDAPI_select中璃氢,調(diào)用select之前又進行了一次多余的映射(1005~1019行),試圖通過RFDMap來從RFD映射到socket狮辽,但由于此時的RFD已經(jīng)是socket了一也,因為RFDMap中并不存在這些key巢寡,結(jié)果就是所有的socket都是INVALID_SOCKET,導致無法成功連接到redis服務器椰苟。
  • 在677行抑月,原redis代碼用pollCopy[i].fd來判斷socket數(shù)量是否超過64的邏輯也是錯誤的,因為經(jīng)過一次映射后pollCopy[i].fd代表的是socket舆蝴,而socket函數(shù)返回的是OS文件描述符谦絮,超過64很正常,應當用fds[i].fd(也就是rfd)來判斷洁仗。另外這部分的check我認為是多余的层皱,也可以直接刪除,因為在667~670行已經(jīng)判斷過了京痢。
    在redis中rfd和OS類似奶甘,0~2也是被占用的,新的fd從3開始祭椰,因此實際上的合法socket數(shù)量不超過62臭家。
  • 吐槽:我覺得select部分和poll部分肯定不是同一個人寫的,所以寫select的人真的很不認真方淤,把fds和pollCopy的涵義完全搞反了并且還沒有進行測試钉赁。或者寫poll的人也許應該把映射部分放在分支內(nèi)進行携茂?就是多了一部分重復代碼你踩。

p.s. 這個PR是不可能merge了,提個PR做提醒也好讳苦,另外這個人好像有在維護這個坑带膜,鏈接在這里,但是沒有修復這個bug(2018.05.14)鸳谜,我也懶得再提一次PR了:https://github.com/tporadowski/redis

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末膝藕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子咐扭,更是在濱河造成了極大的恐慌芭挽,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蝗肪,死亡現(xiàn)場離奇詭異袜爪,居然都是意外死亡,警方通過查閱死者的電腦和手機薛闪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門辛馆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人豁延,你說我怎么就攤上這事昙篙【缶拢” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵瓢对,是天一觀的道長。 經(jīng)常有香客問我胰苏,道長硕蛹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任硕并,我火速辦了婚禮法焰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘倔毙。我一直安慰自己埃仪,他們只是感情好,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布陕赃。 她就那樣靜靜地躺著卵蛉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪么库。 梳的紋絲不亂的頭發(fā)上傻丝,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音诉儒,去河邊找鬼葡缰。 笑死,一個胖子當著我的面吹牛忱反,可吹牛的內(nèi)容都是我干的泛释。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼温算,長吁一口氣:“原來是場噩夢啊……” “哼怜校!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起米者,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤韭畸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蔓搞,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胰丁,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年喂分,在試婚紗的時候發(fā)現(xiàn)自己被綠了锦庸。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡蒲祈,死狀恐怖甘萧,靈堂內(nèi)的尸體忽然破棺而出萝嘁,到底是詐尸還是另有隱情,我是刑警寧澤扬卷,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布牙言,位于F島的核電站,受9級特大地震影響怪得,放射性物質(zhì)發(fā)生泄漏咱枉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一徒恋、第九天 我趴在偏房一處隱蔽的房頂上張望蚕断。 院中可真熱鬧,春花似錦入挣、人聲如沸亿乳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽葛假。三九已至,卻和暖如春滋恬,著一層夾襖步出監(jiān)牢的瞬間桐款,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工夷恍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留魔眨,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓酿雪,卻偏偏與公主長得像遏暴,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子指黎,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容