Skip to content

TST: Non-deterministic test_update_parallel_multi failure on Windows #10914

Closed

Description

@pllim

This started showing up a few days ago but not every run. Need to think about how to handle this so we can proceed with 4.2 feature freeze. I wonder if this is caused by the switch to travis-ci.com too. 🤷

cc @aarchiba in case she has some idea of what is happening.

Example log: https://travis-ci.com/github/astropy/astropy/jobs/403147228

=================================== ERRORS ====================================
_______________ ERROR at teardown of test_update_parallel_multi _______________
tmpdir = local('C:\\Users\\travis\\AppData\\Local\\Temp\\pytest-of-unknown\\pytest-0\\test_update_parallel_multi0')
    @pytest.fixture
    def temp_cache(tmpdir):
        with paths.set_temp_cache(tmpdir):
            yield None
>           check_download_cache()
..\..\.tox\py38-test-alldeps\lib\site-packages\astropy\utils\tests\test_data.py:144: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
check_hashes = False, pkgname = 'astropy'
    def check_download_cache(check_hashes=False, pkgname='astropy'):
        """Do a consistency check on the cache.
    
        Because the cache is shared by all versions of astropy in all virtualenvs
        run by your user, possibly concurrently, it could accumulate problems.
        This could lead to hard-to-debug problems or wasted space. This function
        detects a number of incorrect conditions, including nonexistent files that
        are indexed, files that are indexed but in the wrong place, and, if you
        request it, files whose content does not match the hash that is indexed.
    
        This function also returns a list of non-indexed files. A few will be
        associated with the shelve object; their exact names depend on the backend
        used but will probably be based on ``urlmap``. The presence of other files
        probably indicates that something has gone wrong and inaccessible files
        have accumulated in the cache. These can be removed with
        `clear_download_cache`, either passing the filename returned here, or
        with no arguments to empty the entire cache and return it to a
        reasonable, if empty, state.
    
        Parameters
        ----------
        check_hashes : boolean, optional
            Deprecated; does nothing.
    
        pkgname : `str`, optional
            The package name to use to locate the download cache. i.e. for
            ``pkgname='astropy'`` the default cache location is
            ``~/.astropy/cache``.
    
        Returns
        -------
        strays : set
            Deprecated. The empty set.
    
        Raises
        ------
        CacheDamaged
            To indicate a problem with the cache contents; the exception contains
            a ``.bad_files`` attribute containing a set of filenames to allow the
            user to use `clear_download_cache` to remove the offending items.
        OSError, RuntimeError
            To indicate some problem with the cache structure. This may need a full
            `clear_download_cache` to resolve, or may indicate some kind of
            misconfiguration.
        """
        bad_files = set()
        messages = set()
        dldir = _get_download_cache_loc(pkgname=pkgname)
        with os.scandir(dldir) as it:
            for entry in it:
                f = os.path.abspath(os.path.join(dldir, entry.name))
                if entry.name.startswith("rmtree-"):
                    if f not in _tempfilestodel:
                        bad_files.add(f)
                        messages.add(f"Cache entry {entry.name} not scheduled for deletion")
                elif entry.is_dir():
                    for sf in os.listdir(f):
                        if sf in ['url', 'contents']:
                            continue
                        sf = os.path.join(f, sf)
                        bad_files.add(sf)
                        messages.add(f"Unexpected file f{sf}")
                    urlf = os.path.join(f, "url")
                    url = None
                    if not os.path.isfile(urlf):
                        bad_files.add(urlf)
                        messages.add(f"Problem with URL file f{urlf}")
                    else:
                        url = get_file_contents(urlf, encoding="utf-8")
                        if not _is_url(url):
                            bad_files.add(f)
                            messages.add(f"Malformed URL: {url}")
                        else:
                            hashname = _url_to_dirname(url)
                            if entry.name != hashname:
                                bad_files.add(f)
                                messages.add(f"URL hashes to {hashname} but is stored in {entry.name}")
                    if not os.path.isfile(os.path.join(f, "contents")):
                        bad_files.add(f)
                        if url is None:
                            messages.add(f"Hash {entry.name} is missing contents")
                        else:
                            messages.add(f"URL {url} with hash {entry.name} is missing contents")
                else:
                    bad_files.add(f)
                    messages.add(f"Left-over non-directory {f} in cache")
        if bad_files:
>           raise CacheDamaged("\n".join(messages), bad_files=bad_files)
E           astropy.utils.data.CacheDamaged: Cache entry rmtree-7v3yzo04 not scheduled for deletion
..\..\.tox\py38-test-alldeps\lib\site-packages\astropy\utils\data.py:1692: CacheDamaged
================================== FAILURES ===================================
_________________________ test_update_parallel_multi __________________________
temp_cache = None
valid_urls = <generator object valid_urls.<locals>._valid_urls at 0x00000253AE3D4DD0>
    @pytest.mark.skipif(sys.version_info < (3, 8),
                        reason="causes mystery segfault! possibly bug #10008")
    def test_update_parallel_multi(temp_cache, valid_urls):
        u, c = next(valid_urls)
        iucs = list(islice(valid_urls, N_THREAD_HAMMER))
    
        f = download_file(u, cache=True)
        assert get_file_contents(f) == c
    
        def update(uc):
            u2, c2 = uc
            return download_file(u, cache="update", sources=[u2]), c2
    
        with ThreadPoolExecutor(max_workers=len(iucs)) as P:
>           r = list(P.map(update, iucs))
..\..\.tox\py38-test-alldeps\lib\site-packages\astropy\utils\tests\test_data.py:860: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
c:\python38\lib\concurrent\futures\_base.py:611: in result_iterator
    yield fs.pop().result()
c:\python38\lib\concurrent\futures\_base.py:432: in result
    return self.__get_result()
c:\python38\lib\concurrent\futures\_base.py:388: in __get_result
    raise self._exception
c:\python38\lib\concurrent\futures\thread.py:57: in run
    result = self.fn(*self.args, **self.kwargs)
..\..\.tox\py38-test-alldeps\lib\site-packages\astropy\utils\tests\test_data.py:857: in update
    return download_file(u, cache="update", sources=[u2]), c2
..\..\.tox\py38-test-alldeps\lib\site-packages\astropy\utils\data.py:1246: in download_file
    return import_file_to_cache(url_key, f_name,
..\..\.tox\py38-test-alldeps\lib\site-packages\astropy\utils\data.py:1801: in import_file_to_cache
    _rmtree(local_dirname, replace=temp_dir)
..\..\.tox\py38-test-alldeps\lib\site-packages\astropy\utils\data.py:1746: in _rmtree
    raise
c:\python38\lib\tempfile.py:825: in __exit__
    self.cleanup()
c:\python38\lib\tempfile.py:829: in cleanup
    self._rmtree(self.name)
c:\python38\lib\tempfile.py:811: in _rmtree
    _shutil.rmtree(name, onerror=onerror)
c:\python38\lib\shutil.py:730: in rmtree
    return _rmtree_unsafe(path, onerror)
c:\python38\lib\shutil.py:612: in _rmtree_unsafe
    onerror(os.rmdir, path, sys.exc_info())
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
path = 'C:\\Users\\travis\\AppData\\Local\\Temp\\pytest-of-unknown\\pytest-0\\test_update_parallel_multi0\\astropy\\download\\url\\rmtree-7v3yzo04'
onerror = <function TemporaryDirectory._rmtree.<locals>.onerror at 0x00000253AF60C3A0>
    def _rmtree_unsafe(path, onerror):
        try:
            with os.scandir(path) as scandir_it:
                entries = list(scandir_it)
        except OSError:
            onerror(os.scandir, path, sys.exc_info())
            entries = []
        for entry in entries:
            fullname = entry.path
            if _rmtree_isdir(entry):
                try:
                    if entry.is_symlink():
                        # This can only happen if someone replaces
                        # a directory with a symlink after the call to
                        # os.scandir or entry.is_dir above.
                        raise OSError("Cannot call rmtree on a symbolic link")
                except OSError:
                    onerror(os.path.islink, fullname, sys.exc_info())
                    continue
                _rmtree_unsafe(fullname, onerror)
            else:
                try:
                    os.unlink(fullname)
                except OSError:
                    onerror(os.unlink, fullname, sys.exc_info())
        try:
>           os.rmdir(path)
E           OSError: [WinError 145] The directory is not empty: 'C:\\Users\\travis\\AppData\\Local\\Temp\\pytest-of-unknown\\pytest-0\\test_update_parallel_multi0\\astropy\\download\\url\\rmtree-7v3yzo04'
c:\python38\lib\shutil.py:610: OSError
=========================== short test summary info ===========================
FAILED ..\..\.tox\py38-test-alldeps\lib\site-packages\astropy\utils\tests\test_data.py::test_update_parallel_multi
ERROR ..\..\.tox\py38-test-alldeps\lib\site-packages\astropy\utils\tests\test_data.py::test_update_parallel_multi
= 1 failed, 15319 passed, 255 skipped, 106 xfailed, 1 error in 438.41s (0:07:18) =
ERROR: InvocationError for command 'C:\Users\travis\build\astropy\astropy\.tox\py38-test-alldeps\Scripts\pytest.EXE' --pyargs astropy 'C:\Users\travis\build\astropy\astropy/docs' (exited with code 1)

TODO

  • See if I can reproduce this test failure locally on Windows. (Nope)
  • Is there anything better than just skipping for Windows? (Nothing obvious jumped out after staring at it for 10 mins.)

Activity

  1. added this to the v4.2 milestone on Oct 22, 2020
  2. self-assigned this
    on Oct 22, 2020
  3. removed this from the v4.2 milestone on Oct 22, 2020
  4. bsipocz commented on Nov 25, 2020

    @bsipocz
    Member

    I believe I see this error in the wheel jobs, on pytohn 3.9 (or 3.8? the traceback is very very confusing as both are listed):

    https://dev.azure.com/astropy-project/astropy/_build/results?buildId=719&view=logs&jobId=db1f08a6-b047-57fe-852c-bfc42b7337eb&j=db1f08a6-b047-57fe-852c-bfc42b7337eb&t=d420506b-80e5-534d-d040-77919ee1e297

            try:
    >           os.rmdir(path)
    E           OSError: [WinError 145] The directory is not empty: 'C:\\Users\\VssAdministrator\\AppData\\Local\\Temp\\pytest-of-VssAdministrator\\pytest-0\\test_update_parallel_multi0\\astropy\\download\\url\\rmtree-kl3nd66x'
    
    cibw\python\python.3.8.4\tools\lib\shutil.py:617: OSError
    =========================== short test summary info ===========================
    FAILED users/vssadministrator/appdata/local/temp/tmpbdx6d43y/lib/site-packages/astropy/utils/tests/test_data.py::test_update_parallel
    FAILED users/vssadministrator/appdata/local/temp/tmpbdx6d43y/lib/site-packages/astropy/utils/tests/test_data.py::test_update_parallel_multi
    ERROR users/vssadministrator/appdata/local/temp/tmpbdx6d43y/lib/site-packages/astropy/utils/tests/test_data.py::test_update_parallel
    ERROR users/vssadministrator/appdata/local/temp/tmpbdx6d43y/lib/site-packages/astropy/utils/tests/test_data.py::test_update_parallel_multi
    = 2 failed, 13019 passed, 1064 skipped, 24 deselected, 59 xfailed, 2 errors in 290.20s (0:04:50) =
    Traceback (most recent call last):
      File "c:\hostedtoolcache\windows\python\3.9.0\x64\lib\runpy.py", line 197, in _run_module_as_main
        return _run_code(code, main_globals, None,
      File "c:\hostedtoolcache\windows\python\3.9.0\x64\lib\runpy.py", line 87, in _run_code
        exec(code, run_globals)
      File "C:\hostedtoolcache\windows\Python\3.9.0\x64\Scripts\cibuildwheel.exe\__main__.py", line 7, in <module>
      File "c:\hostedtoolcache\windows\python\3.9.0\x64\lib\site-packages\cibuildwheel\__main__.py", line 236, in main
        cibuildwheel.windows.build(build_options)
      File "c:\hostedtoolcache\windows\python\3.9.0\x64\lib\site-packages\cibuildwheel\windows.py", line 302, in build
        shell(test_command_prepared, cwd='c:\\', env=virtualenv_env)
      File "c:\hostedtoolcache\windows\python\3.9.0\x64\lib\site-packages\cibuildwheel\windows.py", line 31, in shell
        subprocess.check_call(command, env=env, cwd=cwd, shell=True)
      File "c:\hostedtoolcache\windows\python\3.9.0\x64\lib\subprocess.py", line 373, in check_call
        raise CalledProcessError(retcode, cmd)
    subprocess.CalledProcessError: Command 'pytest -p no:warnings --astropy-header -k "not test_data_out_of_range and not test_data_at_range_limit" --pyargs astropy' returned non-zero exit status 1.
    
    ##[error]Bash exited with code '1'.
    Finishing: Running cibuildwheel
    
  5. bsipocz commented on Nov 25, 2020

    @bsipocz
    Member

    (test header says 3.8, but it's a bit confusing, see more details on slack)

  6. pllim commented on Nov 25, 2020

    @pllim
    MemberAuthor

    I think things were resolved on Slack? If there is further action needed regarding this patch, please let me know. Thanks!

  7. bsipocz commented on Nov 25, 2020

    @bsipocz
    Member

    This popped up later in the wheel builds, too, but a restart resolved it. I suppose the we could set CI to True even for azure, to get the skip from the patch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions