Python3多进程子进程首次网络访问时偶发futex_wait_queue_me阻塞
Python多进程子进程网络请求时卡在futex_wait_queue_me状态问题排查
问题现象
- 主程序基于Python3.9开发,通过
multiprocessing模块加载并控制子进程执行短期任务,任务完成后子进程终止 - 部分子进程启动后能正常输出调试日志,但首次发起网络访问时会卡住:既可能是
requests请求,也可能是pymssql数据库连接 - 卡住的子进程会永久处于futex_wait_queue_me状态,无法通过
SIGTERM信号终止,必须使用SIGKILL才能强制停止 - 问题进程的栈信息如下:
cat /proc/12345/stack <0>] futex_wait_queue_me+0xb6/0x110 [<0>] futex_wait+0xe9/0x240 [<0>] do_futex+0x174/0xbc0 [<0>] __x64_sys_futex+0x146/0x1c0 [<0>] do_syscall_64+0x33/0x80 [<0>] entry_SYSCALL_64_after_hwframe+0x44/0xa9
已尝试的无效方案
怀疑父进程继承的文件句柄携带锁,在子进程初始化时添加os.closerange(3,100)关闭除stdin/stdout/stderr外的所有句柄,但问题依旧。相关代码如下:
def startSub(params, config): sub=Process(target=SubModule, args=(params, config)) sub.daemon=True sub.start() return sub # 子进程独立运行至终止,无IPC,仅通过sub.is_alive()监控状态 class SubModule: def __init__(self, params, config): os.closerange(3,100) setproctitle("Submodule") # 标识进程名称 log.debug("Starting stuff") # 该日志能正常输出 result=requests.get("https://somewhere.org") # 此处偶尔会卡住不返回 log.debug("came back from requests") # 卡住时不会执行到这里
GDB调试回溯信息
程序运行在python3.9-slim-bullseye容器中,添加gdb后捕获到的Python层回溯:
(gdb) py-bt Traceback (most recent call first): <built-in method getaddrinfo of module object at remote 0x7f4fd9634350> File "/usr/lib/python3.9/socket.py", line 953, in getaddrinfo for res in _socket.getaddrinfo(host, port, family, type, proto, flags): File "/usr/lib/python3/dist-packages/urllib3/util/connection.py", line 329, in create_connection File "/usr/lib/python3/dist-packages/urllib3/connection.py", line 681, in _new_conn File "/usr/lib/python3/dist-packages/urllib3/connection.py", line 353, in connect conn = self._new_conn() File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 1012, in _validate_conn conn.connect() File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 382, in _make_request self._validate_conn(conn) File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 1467, in urlopen File "/usr/lib/python3/dist-packages/requests/adapters.py", line 951, in send File "/usr/lib/python3/dist-packages/requests/sessions.py", line 655, in send r = adapter.send(request, **kwargs) File "/usr/lib/python3/dist-packages/requests/sessions.py", line 1310, in request File "/usr/lib/python3/dist-packages/requests/api.py", line 61, in request
底层C栈信息显示,程序卡在_socket.getaddrinfo(host, port, socket.AF_INET, socket.SOCK_STREAM, 0)调用内部:
(gdb) bt #0 0x00007f4fd9c19d66 in ?? () from /lib/x86_64-linux-gnu/libc.so.6 #1 0x00007f4fd9cb4bed in ?? () from /lib/x86_64-linux-gnu/libc.so.6 #2 0x00007f4fd9cb4fcb in ?? () from /lib/x86_64-linux-gnu/libc.so.6 #3 0x00007f4fd9cb3955 in ?? () from /lib/x86_64-linux-gnu/libc.so.6 #4 0x00007f4fd9cb474b in ?? () from /lib/x86_64-linux-gnu/libc.so.6 #5 0x00007f4fd9cb48d3 in __resolv_context_get () from /lib/x86_64-linux-gnu/libc.so.6 #6 0x00007f4fd9ca54e9 in gethostbyname2_r () from /lib/x86_64-linux-gnu/libc.so.6 #7 0x00007f4fd9c7cfac in ?? () from /lib/x86_64-linux-gnu/libc.so.6 #8 0x00007f4fd9c7db25 in getaddrinfo () from /lib/x86_64-linux-gnu/libc.so.6 #9 0x0000000000615b1e in socket_getaddrinfo (self=<optimized out>, args=<optimized out>, kwargs=<optimized out>) at ../Modules/socketmodule.c:6574 #10 0x000000000065e4fd in cfunction_call (func=<built-in method getaddrinfo of module object at remote 0x7f4fd9634350>, args=<optimized out>, kwargs=<optimized out>) at ../Objects/methodobject.c:539
注:此问题并非常见的getaddrinfo调用锁死情况,而是卡在getaddrinfo内部的锁机制中。
目前毫无头绪,求解释这一现象?
内容的提问来源于stack exchange,提问作者Andreas
相关产品推荐
相关产品推荐

