2017-05-03 246 views
1

這裏是我的項目的簡單的演示:Socket.getaddrinfo卡,在使用Python請求時無限期阻塞過程

import requests 
import json, time 
import socket 
socket.setdefaulttimeout(2) 
def request(url, msg=None, timeout=2, method="get"): 
    flag, resp = False, None 
    try: 
     if method == "get": 
      resp = requests.get(url, params=msg, timeout=timeout, verify=False) 
    elif method == "post": 
     resp = requests.post(url, data=msg, timeout=timeout, verify=False) 
    elif method == "delete": 
     s=requests.Session() 
     resp = s.delete(url, data=msg, timeout=timeout, verify=False) 

    flag = True 
    except requests.exceptions.Timeout: 
     resp = "time_out" 
    except requests.exceptions.TooManyRedirects: 
     resp = "too_many_redirect" 
    except requests.ConnectionError as err: 
     resp = "connection_error" 
    except requests.exceptions.RequestException as err: 
     resp = str(err.__class__.__name__) 

    return flag, resp 

if __name__ == '__main__': 
    while True: 
     print request("https://www.google.com", timeout=1) 
     time.sleep(1) 

運行一段時間的過程中會阻擋,當我的pstack我總是看到這個之後:

Thread 3 (Thread 0x7f465f310700 (LWP 22537)): 
#0 0x00000030dd0e993d in recvmsg() from /lib64/libc.so.6 
#1 0x00000030dd10f8d5 in make_request() from /lib64/libc.so.6 
#2 0x00000030dd10fd0a in __check_pf() from /lib64/libc.so.6 
#3 0x00000030dd0d2ec7 in getaddrinfo() from /lib64/libc.so.6 
#4 0x00007f46647e07bf in socket_getaddrinfo() from ... 

我找到了一個消息here和已知查詢DNS當它被封鎖,我已經爲請求超時,但它是沒用的!有人遇到過這個問題嗎?謝謝你的幫助。

回答

0

經過Google長時間的搜索後,我發現這個帖子[Bug libc/12926] getaddrinfo()/make_request() may spin forever,並修復了該錯誤The GNU C Library version 2.23。但是在我的機器上更新glibc是不可能的。

我曾經編寫使用請求模塊也python程序,所以我仔細比較兩者,它不存在這個問題,我發現最大的區別就是其使用線程的數量請求http請求。第一個只有一個線程使用請求,但最後一個有兩個,所以我把程序重構爲單個線程程序進行測試。這個問題從來沒有發生過。

man page of requests表示請求是線程安全的,我還沒有找到這個錯誤的確切原因,所以我只是使用單線程方法來避免這個問題。

如果有人知道任何意見將不勝感激。