Socket.getaddrinfo卡住了,在python中使用请求时无限期地阻塞了进程

时间:2017-05-03 16:22:15

标签: python python-requests blocking

这是我项目的简单演示:

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时阻塞了我已经为请求设置了超时,但它没用!有没有人遇到过这个问题?谢谢你的帮助。

1 个答案:

答案 0 :(得分: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表示请求是线程安全的,我还没有找到这个bug的确切原因,所以我只使用单线程方法来避免这个问题。

如果有人知道任何建议都会受到赞赏。