Skip to content

test_imaplib failed with ConnectionRefusedError on AMD64 FreeBSD Refleaks 3.15 buildbot #161336

Closed

Description

@vstinner

Build: https://buildbot.python.org/#/builders/2056/builds/483

Would it be possible to skip the test on a network error? Or would it defeat the purpose of the test?

test_imaplib_timeout_functionality_test (test.test_imaplib.NewIMAPSSLTests.test_imaplib_timeout_functionality_test) ... SENT: b'* OK IMAP4rev1'
GOT: b'JKNP0 CAPABILITY'
SENT: b'* CAPABILITY IMAP4rev1'
SENT: b'JKNP0 OK CAPABILITY completed'
ERROR

======================================================================
ERROR: test_imaplib_timeout_functionality_test (test.test_imaplib.NewIMAPSSLTests.test_imaplib_timeout_functionality_test)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/buildbot/buildarea/3.15.opsec-fbsd14.refleak/build/Lib/test/test_imaplib.py", line 745, in test_imaplib_timeout_functionality_test
    client = self.imap_class("localhost", addr, timeout=0.001)
  File "/home/buildbot/buildarea/3.15.opsec-fbsd14.refleak/build/Lib/imaplib.py", line 1772, in __init__
    IMAP4.__init__(self, host, port, timeout)
    ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/buildbot/buildarea/3.15.opsec-fbsd14.refleak/build/Lib/imaplib.py", line 217, in __init__
    self.open(host, port, timeout)
    ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
  File "/home/buildbot/buildarea/3.15.opsec-fbsd14.refleak/build/Lib/imaplib.py", line 1785, in open
    IMAP4.open(self, host, port, timeout)
    ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/buildbot/buildarea/3.15.opsec-fbsd14.refleak/build/Lib/imaplib.py", line 331, in open
    self.sock = self._create_socket(timeout)
                ~~~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/home/buildbot/buildarea/3.15.opsec-fbsd14.refleak/build/Lib/imaplib.py", line 1775, in _create_socket
    sock = IMAP4._create_socket(self, timeout)
  File "/home/buildbot/buildarea/3.15.opsec-fbsd14.refleak/build/Lib/imaplib.py", line 320, in _create_socket
    return socket.create_connection(address, timeout)
           ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "/home/buildbot/buildarea/3.15.opsec-fbsd14.refleak/build/Lib/socket.py", line 887, in create_connection
    raise exceptions[0]
  File "/home/buildbot/buildarea/3.15.opsec-fbsd14.refleak/build/Lib/socket.py", line 872, in create_connection
    sock.connect(sa)
    ~~~~~~~~~~~~^^^^
ConnectionRefusedError: [Errno 61] Connection refused

Linked PRs

Activity

  1. added
    type-bugAn unexpected behavior, bug, or error
    testsTests in the Lib/test dir
    on Nov 4, 2026
  2. NekoAsakura commented on Nov 4, 2026

    @NekoAsakura
    Member

    Well, the test connects to the wrong host. On FreeBSD:

    $ grep localhost /etc/hosts
    ::1			localhost localhost.my.domain
    127.0.0.1		localhost localhost.my.domain
    

    We could fix instead of skip.

  3. vstinner commented on Nov 5, 2026

    @vstinner
    MemberAuthor

    Well, the test connects to the wrong host.

    Can you elaborate? Which host is used? I would expect "localhost" to be resolved to 127.0.0.1 (IPv4) or ::1 (IPv6), the local loopback. So it should just work, no?

  4. vstinner commented on Nov 5, 2026

    @vstinner
    MemberAuthor

    I failed to reproduce the issue on FreeBSD:

    vstinner@freebsd$ ./python -m test test_imaplib -u all -m test_imaplib_timeout_functionality_test -v
    (...)
    == Tests result: SUCCESS ==
    (...)
    
  5. NekoAsakura commented on Nov 5, 2026

    @NekoAsakura
    Member

    or ::1 (IPv6)

    That's the problem. The server only listens on 127.0.0.1. If that connect takes over 1 ms, the TimeoutError is dropped (L890) and ::1 is tried next, which is refused.

    cpython/Lib/socket.py

    Lines 874 to 891 in f8e65ee

    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
    af, socktype, proto, canonname, sa = res
    sock = None
    try:
    sock = socket(af, socktype, proto)
    if timeout is not _GLOBAL_DEFAULT_TIMEOUT:
    sock.settimeout(timeout)
    if source_address:
    sock.bind(source_address)
    sock.connect(sa)
    # Break explicitly a reference cycle
    exceptions.clear()
    return sock
    except error as exc:
    if not all_errors:
    exceptions.clear() # raise only the last error
    exceptions.append(exc)

    To reproduce, you need to add some latency on ipv4 loopback with tc netem.

  6. vstinner commented on Nov 5, 2026

    @vstinner
    MemberAuthor

    Wait. What is this 1 ms timeout? Why not using support.LOOPBACK_TIMEOUT (10 sec by default).

  7. NekoAsakura commented on Nov 5, 2026

    @NekoAsakura
    Member

    What is this 1 ms timeout?

    Because the test wants a TimeoutError(by set a very short timeout); the problem is that it gets dropped.

    def test_imaplib_timeout_functionality_test(self):
    class TimeoutHandler(SimpleIMAPHandler):
    def handle(self):
    time.sleep(1)
    SimpleIMAPHandler.handle(self)
    _, server = self._setup(TimeoutHandler)
    addr = server.server_address[1]
    with self.assertRaises(TimeoutError):
    client = self.imap_class("localhost", addr, timeout=0.001)

  8. NekoAsakura commented on Nov 5, 2026

    @NekoAsakura
    Member

    Let me spell out the logic. The test expects a TimeoutError. The handler sleeps 1s before the greeting and the client waits 1 ms, so normally the connect to 127.0.0.1 succeeds and the timeout hits while reading the greeting.

    On a busy machine the connect itself can take over 1 ms. With localhost, create_connection() drops that TimeoutError, moves on to ::1 where nothing listens, and reports only the last error, which is ConnectionRefusedError. With server.server_address there is a single address, so a slow connect raises TimeoutError as well.

  9. added a commit that references this issue on Nov 5, 2026
  10. vstinner commented on Nov 5, 2026

    @vstinner
    MemberAuthor

    create_connection() drops that TimeoutError, moves on to ::1

    Oh. That's subtle: create_connection() catches OSError and moves to the next IP address, and TimeoutError is a OSError sub-class. I see. I merged your fix.

  11. added 2 commits that reference this issue on Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    testsTests in the Lib/test dirtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions