Endless polling EOF socket
まだ誰も着手していません。
- 主要言語
- Python
- スター
- 77.2k
- フォーク
- 35.9k
- PR マージ指標
- PR 指標を取得中
説明
Bug report
Bug description:
Hello,
I have this very simple code to attempt a TCP connection to a given host. The linux machine where I run this has tsocks library installed, to transparently redirect connections over socks server. If the target IP accessed through the socks server refuses the connection, the code will end in an endless unbreakable loop.
def tcp_connect(ip, port):
"""Attempt a TCP connection to the given IP and port."""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5)
result = sock.connect_ex((ip, port))
sock.close()
Timeout has no effect, ctrl+c on the console doesn't break it.
Connection attempt with some command line utility ends correctly.
$ ssh 1.1.1.1
ssh: connect to host 1.1.1.1 port 22: Transport endpoint is not connected
$ ldp telnet 1.1.1.1 22
Trying 1.1.1.1...
telnet: Unable to connect to remote host: Transport endpoint is not connected
I tried running strace to see what happens during that endless loop and this is the result :
getpeername(3, 0x7ffd6c12e3f0, [16]) = -1 ENOTCONN (Transport endpoint is not connected)
connect(3, {sa_family=AF_INET, sin_port=htons(2224), sin_addr=inet_addr("172.17.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
poll([{fd=3, events=POLLOUT}], 1, 5000) = 1 ([{fd=3, revents=POLLOUT}])
connect(3, {sa_family=AF_INET, sin_port=htons(2224), sin_addr=inet_addr("172.17.0.1")}, 16) = 0
sendto(3, "\5\2\0\2", 4, 0, NULL, 0) = 4
recvfrom(3, "\5\0", 2, 0, NULL, NULL) = 2
sendto(3, "\5\1\0\1\225\203f\211\0\26", 10, 0, NULL, 0) = 10
recvfrom(3, 0x55944406ddd8, 10, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
poll([{fd=3, events=POLLIN}], 1, 5000) = 1 ([{fd=3, revents=POLLIN}])
recvfrom(3, "", 10, 0, NULL, NULL) = 0
poll([{fd=3, events=POLLIN}], 1, 5000) = 1 ([{fd=3, revents=POLLIN}])
recvfrom(3, "", 10, 0, NULL, NULL) = 0
poll([{fd=3, events=POLLIN}], 1, 5000) = 1 ([{fd=3, revents=POLLIN}])
recvfrom(3, "", 10, 0, NULL, NULL) = 0
poll([{fd=3, events=POLLIN}], 1, 5000) = 1 ([{fd=3, revents=POLLIN}])
recvfrom(3, "", 10, 0, NULL, NULL) = 0
poll([{fd=3, events=POLLIN}], 1, 5000) = 1 ([{fd=3, revents=POLLIN}])
recvfrom(3, "", 10, 0, NULL, NULL) = 0
<continues until sigkill while hogging 100% CPU>
I don't understand it that much, but LLM seems to believe, that the socket is getting polled despite EOF, which is supposedly an error.
Edit:
For comparison, this is how the strace on that telnet looks like
getpeername(3, 0x7ffd4d54e260, [16]) = -1 ENOTCONN (Transport endpoint is not connected)
connect(3, {sa_family=AF_INET, sin_port=htons(2224), sin_addr=inet_addr("172.17.0.1")}, 16) = 0
sendto(3, "\5\2\0\2", 4, 0, NULL, 0) = 4
recvfrom(3, "\5\0", 2, 0, NULL, NULL) = 2
sendto(3, "\5\1\0\1\225\203f\211\0\26", 10, 0, NULL, 0) = 10
recvfrom(3, "", 10, 0, NULL, NULL) = 0
write(2, "telnet: Unable to connect to rem"..., 78telnet: Unable to connect to remote host: Transport endpoint is not connected
) = 78
close(3) = 0
exit_group(1) = ?
+++ exited with 1 +++
Thank you for your attention.
CPython versions tested on:
3.10
Operating systems tested on:
Linux
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
レポート内の tcp_connect スニペットから始め、Linux 上で Python 3.10 と tsocks を使って再現し、その後、動作する telnet のケースと strace を比較します。繰り返される EOF 読み取りの周辺で socket と connect_ex の挙動を追跡し、ループが CPython にあるのか透過プロキシ層にあるのかを特定します。責任のある挙動が特定され、issue に再現可能な回帰テストまたは明確な解決策がある状態を完了とします。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- python
- 領域
- networking
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 静か
- 明瞭さ
- 説明が足りない
- 初心者へのやさしさ
- 45/100