Describe the bug
While working on my library based on apache-libcloud, I used the local provider to use the filesystem as an object storage.
While I wanted to mix this with pyfakefs in my unit test, this resulted in a bad file descriptor error in the test teadown, with a potential conflict between the fasteners library and pyfakefs logic.
How To Reproduce
Surprisingly, I found this bug only when running my test suite on Github Actions.
Running it on my laptop works fine, and I have no clue at this point with the Python environment would be different in Github Actions.
I build a small repository for you to test this issue and have a 100% repro:
https://github.com/Wenzel/test_bug_pyfaefs_github_actions/tree/test
(Please note the test branch where from which I have opened a pull request to trigger Github Actions and have a repro)
I created 2 tests:
test_fake_fs
test_no_fake_fs
Each one will use a fixture to create a libcloud object storage driver based on the local provider (filesystem), but one of them also uses pyfakefs, instead of the real filesystem.
When the fake filesystem is used, the teardown fails, as you can see below. (But only on Github Actions ❓ ❗ )
This is the stacktrace that I get on Github Actions:
==================================== ERRORS ====================================
______________________ ERROR at teardown of test_fake_fs _______________________
self = <fasteners.process_lock._FcntlLock object at 0x7fd702951dc0>
blocking = True, watch = <fasteners._utils.StopWatch object at 0x7fd702951f40>
def _try_acquire(self, blocking, watch):
try:
> self.trylock()
../../../.cache/pypoetry/virtualenvs/test-bad-file-descriptor-gyJ7bpKD-py3.8/lib/python3.8/site-packages/fasteners/process_lock.py:78:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <fasteners.process_lock._FcntlLock object at 0x7fd702951dc0>
def trylock(self):
> self._trylock(self.lockfile)
../../../.cache/pypoetry/virtualenvs/test-bad-file-descriptor-gyJ7bpKD-py3.8/lib/python3.8/site-packages/fasteners/process_lock.py:196:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
lockfile = <pyfakefs.fake_filesystem.FakeFileWrapper object at 0x7fd7029670a0>
@staticmethod
def _trylock(lockfile):
> fcntl.lockf(lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
E OSError: [Errno 9] Bad file descriptor
../../../.cache/pypoetry/virtualenvs/test-bad-file-descriptor-gyJ7bpKD-py3.8/lib/python3.8/site-packages/fasteners/process_lock.py:432: OSError
During handling of the above exception, another exception occurred:
fs = <pyfakefs.fake_filesystem.FakeFilesystem object at 0x7fd701d1d610>
tmp_dir = PosixPath('/tmp/tmprt34tghc')
@pytest.fixture
def libcloud_driver_fake_fs(fs, tmp_dir):
"""Initializes libcloud based on the fake filesystem PyFakeFS"""
with libcloud_driver(tmp_dir) as driver:
> yield driver
tests/test_01.py:32:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/opt/hostedtoolcache/Python/3.8.12/x64/lib/python3.8/contextlib.py:120: in __exit__
next(self.gen)
tests/test_01.py:25: in libcloud_driver
driver.delete_container(cont)
../../../.cache/pypoetry/virtualenvs/test-bad-file-descriptor-gyJ7bpKD-py3.8/lib/python3.8/site-packages/libcloud/storage/drivers/local.py:664: in delete_container
with LockLocalStorage(path):
../../../.cache/pypoetry/virtualenvs/test-bad-file-descriptor-gyJ7bpKD-py3.8/lib/python3.8/site-packages/libcloud/storage/drivers/local.py:89: in __enter__
success = self.ipc_lock.acquire(blocking=True,
../../../.cache/pypoetry/virtualenvs/test-bad-file-descriptor-gyJ7bpKD-py3.8/lib/python3.8/site-packages/fasteners/process_lock.py:140: in acquire
gotten = r(self._try_acquire, blocking, watch)
../../../.cache/pypoetry/virtualenvs/test-bad-file-descriptor-gyJ7bpKD-py3.8/lib/python3.8/site-packages/fasteners/_utils.py:124: in __call__
return fn(*args, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <fasteners.process_lock._FcntlLock object at 0x7fd702951dc0>
blocking = True, watch = <fasteners._utils.StopWatch object at 0x7fd702951f40>
def _try_acquire(self, blocking, watch):
try:
self.trylock()
except IOError as e:
if e.errno in (errno.EACCES, errno.EAGAIN):
if not blocking or watch.expired():
return False
else:
raise _utils.RetryAgain()
else:
> raise threading.ThreadError("Unable to acquire lock on"
" `%(path)s` due to"
" %(exception)s" %
{
'path': self.path,
'exception': e,
})
E RuntimeError: Unable to acquire lock on `b'/tmp/3abf221e48c97e8e7239ce5aceb53aeb2296dd948939cb89e08856bede3265c6.lock'` due to [Errno 9] Bad file descriptor
../../../.cache/pypoetry/virtualenvs/test-bad-file-descriptor-gyJ7bpKD-py3.8/lib/python3.8/site-packages/fasteners/process_lock.py:86: RuntimeError
=========================== short test summary info ============================
ERROR tests/test_01.py::test_fake_fs - RuntimeError: Unable to acquire lock o...
========================== 2 passed, 1 error in 0.28s ==========================
Your environment
My local environment
Linux-5.4.0-88-generic-x86_64-with-Ubuntu-20.04-focal
('Python', '2.7.18 (default, Mar 8 2021, 13:02:45) \n[GCC 9.3.0]')
pyfakefs 4.5.1
I hope you have enough information at this point to better understand / investigate the bug.
Feel free to ask for more context !
Thank you for maintaining pyfakefs 🙂
Describe the bug
While working on my library based on apache-libcloud, I used the
localprovider to use the filesystem as an object storage.While I wanted to mix this with pyfakefs in my unit test, this resulted in a bad file descriptor error in the test teadown, with a potential conflict between the fasteners library and pyfakefs logic.
How To Reproduce
Surprisingly, I found this bug only when running my test suite on Github Actions.
Running it on my laptop works fine, and I have no clue at this point with the Python environment would be different in Github Actions.
I build a small repository for you to test this issue and have a 100% repro:
https://github.com/Wenzel/test_bug_pyfaefs_github_actions/tree/test
(Please note the
testbranch where from which I have opened a pull request to trigger Github Actions and have a repro)I created 2 tests:
test_fake_fstest_no_fake_fsEach one will use a fixture to create a libcloud object storage driver based on the
localprovider (filesystem), but one of them also uses pyfakefs, instead of the real filesystem.When the fake filesystem is used, the teardown fails, as you can see below. (But only on Github Actions ❓ ❗ )
This is the stacktrace that I get on Github Actions:
Your environment
My local environment
I hope you have enough information at this point to better understand / investigate the bug.
Feel free to ask for more context !
Thank you for maintaining pyfakefs 🙂