Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test_asyncio: ProactorEventLoopTests sendfile tests leak references on Windows #76891

Closed
vstinner opened this issue Jan 29, 2018 · 17 comments
Closed
Labels
3.7 (EOL) end of life 3.8 only security fixes topic-asyncio

Comments

@vstinner
Copy link
Member

BPO 32710
Nosy @vstinner, @giampaolo, @asvetlov, @1st1, @miss-islington
PRs
  • bpo-32710: test_asyncio: test_sendfile reset policy #11461
  • bpo-32710: test_asyncio: test_sendfile reset policy #11461
  • bpo-32710: test_asyncio: test_sendfile reset policy #11461
  • bpo-32710: Fix leak in Overlapped_WSASend() #11469
  • bpo-32710: Fix leak in Overlapped_WSASend() #11469
  • bpo-32710: Fix leak in Overlapped_WSASend() #11469
  • [3.7] bpo-32710: Fix leak in Overlapped_WSASend() (GH-11469) #11471
  • [3.7] bpo-32710: Fix leak in Overlapped_WSASend() (GH-11469) #11471
  • [3.7] bpo-32710: Fix leak in Overlapped_WSASend() (GH-11469) #11471
  • bpo-32710: Fix _overlapped.Overlapped memory leaks #11489
  • bpo-32710: Fix _overlapped.Overlapped memory leaks #11489
  • bpo-32710: Fix _overlapped.Overlapped memory leaks #11489
  • [3.7] bpo-32710: Fix _overlapped.Overlapped memory leaks (GH-11489) #11519
  • [3.7] bpo-32710: Fix _overlapped.Overlapped memory leaks (GH-11489) #11519
  • [3.7] bpo-32710: Fix _overlapped.Overlapped memory leaks (GH-11489) #11519
  • Files
  • test_aiosend.py
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2019-01-08.13:46:28.897>
    created_at = <Date 2018-01-29.12:43:38.826>
    labels = ['3.7', '3.8', 'expert-asyncio']
    title = 'test_asyncio: ProactorEventLoopTests sendfile tests leak references on Windows'
    updated_at = <Date 2019-01-11.14:11:20.876>
    user = 'https://github.com/vstinner'

    bugs.python.org fields:

    activity = <Date 2019-01-11.14:11:20.876>
    actor = 'vstinner'
    assignee = 'none'
    closed = True
    closed_date = <Date 2019-01-08.13:46:28.897>
    closer = 'vstinner'
    components = ['asyncio']
    creation = <Date 2018-01-29.12:43:38.826>
    creator = 'vstinner'
    dependencies = []
    files = ['48030']
    hgrepos = []
    issue_num = 32710
    keywords = ['patch', 'patch', 'patch']
    message_count = 17.0
    messages = ['311116', '311122', '311151', '315727', '320157', '321007', '333188', '333193', '333198', '333207', '333227', '333228', '333229', '333230', '333467', '333470', '333472']
    nosy_count = 5.0
    nosy_names = ['vstinner', 'giampaolo.rodola', 'asvetlov', 'yselivanov', 'miss-islington']
    pr_nums = ['11461', '11461', '11461', '11469', '11469', '11469', '11471', '11471', '11471', '11489', '11489', '11489', '11519', '11519', '11519']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = None
    url = 'https://bugs.python.org/issue32710'
    versions = ['Python 3.7', 'Python 3.8']

    @vstinner
    Copy link
    Member Author

    AMD64 Windows8.1 Refleaks 3.x:
    http://buildbot.python.org/all/#/builders/80/builds/118

    test_asyncio leaked [4, 4, 3] memory blocks, sum=11

    I reproduced the issue. I'm running test.bisect to try to isolate this bug.

    @vstinner
    Copy link
    Member Author

    It seems to be related to sendfile():

    C:\vstinner\python\master>python -m test -R 3:3 test_asyncio -m test.test_asyncio.test_events.ProactorEventLoopTests.test_sendfile_close_peer_in_middle_of_receiving
    Running Debug|x64 interpreter...
    Run tests sequentially
    0:00:00 [1/1] test_asyncio
    beginning 6 repetitions
    123456
    ......
    test_asyncio leaked [1, 2, 1] memory blocks, sum=4
    test_asyncio failed

    1 test failed:
    test_asyncio

    Total duration: 1 sec
    Tests result: FAILURE

    @1st1
    Copy link
    Member

    1st1 commented Jan 29, 2018

    Andrew, please take a look. I'll have very limited (to no at all) time to work on Python in the next 2 weeks.

    @vstinner
    Copy link
    Member Author

    The test is still leaking memory blocks. Any progress on investigating the issue?

    @vstinner vstinner added the 3.8 only security fixes label Apr 25, 2018
    @vstinner
    Copy link
    Member Author

    Oh, I found again this bug while working on my PR 7827 (detect handle leaks on Windows in regrtest).

    @vstinner vstinner changed the title test_asyncio leaked [4, 4, 3] memory blocks, sum=11 on AMD64 Windows8.1 Refleaks 3.x test_asyncio: ProactorEventLoopTests.test_sendfile_close_peer_in_middle_of_receiving() leaked [4, 4, 3] memory blocks on AMD64 Windows8.1 Refleaks 3.x Jul 3, 2018
    @vstinner
    Copy link
    Member Author

    vstinner commented Jul 3, 2018

    See also bpo-33735: my commit 23401fb fixes a false alarm in regrtest when hunting leaks in test_multiprocessing_spawn or test_multiprocessing_forkserver.

    @vstinner
    Copy link
    Member Author

    vstinner commented Jan 7, 2019

    New changeset df8e1fb by Victor Stinner in branch 'master':
    bpo-32710: test_asyncio: test_sendfile reset policy (GH-11461)
    df8e1fb

    @vstinner vstinner changed the title test_asyncio: ProactorEventLoopTests.test_sendfile_close_peer_in_middle_of_receiving() leaked [4, 4, 3] memory blocks on AMD64 Windows8.1 Refleaks 3.x test_asyncio: ProactorEventLoopTests sendfile tests leak references on Windows Jan 8, 2019
    @vstinner
    Copy link
    Member Author

    vstinner commented Jan 8, 2019

    Update:

    • test.test_asyncio.test_sendfile.ProactorEventLoopTests.test_sendfile_close_peer_in_the_middle_of_receiving leaks 1 reference per run: this bug is caused by bpo-35682 and fixed by PR 11462
    • test.test_asyncio.test_sendfile.ProactorEventLoopTests.test_sendfile_fallback_close_peer_in_the_middle_of_receiving leaks 1 reference per run: I don't understand why.

    I spent a lot of time to investigate test_sendfile_fallback_close_peer_in_the_middle_of_receiving() leak and I don't understand the issue. The main loop is BaseEventLoop._sendfile_fallback(). For the specific case of this test, the loop can be simplified to:

            proto = _SendfileFallbackProtocol(transp)
            try:
                while True:
                    data = b'x' * (1024 * 64)
                    await proto.drain()
                    transp.write(data)
            finally:
                await proto.restore()

    The server closes the connection after it gets 1024 bytes. The client socket gets a ConnectionAbortedError exception in _ProactorBaseWritePipeTransport._loop_writing() which calls _fatal_error():

            except OSError as exc:
                self._fatal_error(exc, 'Fatal write error on pipe transport')

    _fatal_error() calls _force_close() which sets _closing to True and calls protocol.connection_lost(). In the meanwhile, drain() raises ConnectionError because is_closing() is true:

        async def drain(self):
            if self._transport.is_closing():
                raise ConnectionError("Connection closed by peer")
            ...

    @vstinner
    Copy link
    Member Author

    vstinner commented Jan 8, 2019

    Interesting commit. No idea if it's related.

    commit 79790bc
    Author: Victor Stinner <vstinner@redhat.com>
    Date: Fri Jun 8 00:25:52 2018 +0200

    bpo-33694: Fix race condition in asyncio proactor (GH-7498)
    
    The cancellation of an overlapped WSARecv() has a race condition
    which causes data loss because of the current implementation of
    proactor in asyncio.
    
    No longer cancel overlapped WSARecv() in _ProactorReadPipeTransport
    to work around the race condition.
    
    Remove the optimized recv_into() implementation to get simple
    implementation of pause_reading() using the single _pending_data
    attribute.
    
    Move _feed_data_to_bufferred_proto() to protocols.py.
    
    Remove set_protocol() method which became useless.
    

    @vstinner
    Copy link
    Member Author

    vstinner commented Jan 8, 2019

    Attached test_aiosend.py is a simplified version of test to trigger the reference leak. Copy it to Lib/test/ and run:

    vstinner@WIN C:\vstinner\python\master>python -m test test_aiosend -R 3:3
    Running Debug|x64 interpreter...
    Run tests sequentially
    0:00:00 [1/1] test_aiosend
    beginning 6 repetitions
    123456
    ......
    test_aiosend leaked [1, 1, 1] references, sum=3
    test_aiosend leaked [1, 2, 1] memory blocks, sum=4
    test_aiosend failed

    == Tests result: FAILURE ==

    1 test failed:
    test_aiosend

    Total duration: 548 ms
    Tests result: FAILURE

    @vstinner
    Copy link
    Member Author

    vstinner commented Jan 8, 2019

    It took me 1 year, a few sleepless nights, multiple attempts to understand the leak, but I eventually found it! WSASend() doesn't release the memory if it fails immediately. I wrote PR 11469 to fix the memory leak. ReadFile() has the same bug, I also fixed it.

    By the way, the _overlapped.Overlapped type has no traverse function: it may help the garbage collector to add once, since asyncio is famous for building reference cycles by design (Future.set_exception()).

    @vstinner
    Copy link
    Member Author

    vstinner commented Jan 8, 2019

    New changeset a234e14 by Victor Stinner in branch 'master':
    bpo-32710: Fix leak in Overlapped_WSASend() (GH-11469)
    a234e14

    @vstinner
    Copy link
    Member Author

    vstinner commented Jan 8, 2019

    I ran test_asyncio refleak hunting on Windows, and there is no more leak!

    vstinner@WIN C:\vstinner\python\master>python -m test test_asyncio -R 3:3
    (...)
    Total duration: 13 min 24 sec
    Tests result: SUCCESS

    I will close this PR once the 3.7 backport is merged.

    @miss-islington
    Copy link
    Contributor

    New changeset 88ad48b by Miss Islington (bot) in branch '3.7':
    bpo-32710: Fix leak in Overlapped_WSASend() (GH-11469)
    88ad48b

    @vstinner vstinner closed this as completed Jan 8, 2019
    @vstinner
    Copy link
    Member Author

    New changeset 5485085 by Victor Stinner in branch 'master':
    bpo-32710: Fix _overlapped.Overlapped memory leaks (GH-11489)
    5485085

    @miss-islington
    Copy link
    Contributor

    New changeset 059997d by Miss Islington (bot) in branch '3.7':
    bpo-32710: Fix _overlapped.Overlapped memory leaks (GH-11489)
    059997d

    @vstinner
    Copy link
    Member Author

    Ok, _overlapped.Overlapped should now have a few less memory leaks :-)

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.7 (EOL) end of life 3.8 only security fixes topic-asyncio
    Projects
    None yet
    Development

    No branches or pull requests

    3 participants