diff --git a/oauth2client/multistore_file.py b/oauth2client/multistore_file.py index f5a8593..5a12797 100644 --- a/oauth2client/multistore_file.py +++ b/oauth2client/multistore_file.py @@ -290,6 +290,9 @@ class _MultiStore(object): elif e.errno == errno.ENOLCK: logger.warn('File system is out of resources for writing the ' 'credentials file (is your disk full?).') + elif e.errno == errno.EDEADLK: + logger.warn('Lock contention on multistore file, opening ' + 'in read-only mode.') else: raise if not self._file.is_locked(): diff --git a/tests/test_multistore_file.py b/tests/test_multistore_file.py new file mode 100644 index 0000000..1e8c501 --- /dev/null +++ b/tests/test_multistore_file.py @@ -0,0 +1,43 @@ +"""Unit tests for oauth2client.multistore_file.""" + +import errno +import os +import tempfile +import unittest + +from oauth2client import multistore_file + + +class _MockLockedFile(object): + + def __init__(self, filename_str, error_code): + self.filename_str = filename_str + self.error_code = error_code + self.open_and_lock_called = False + + def open_and_lock(self): + self.open_and_lock_called = True + raise IOError(self.error_code, '') + + def is_locked(self): + return False + + def filename(self): + return self.filename_str + + +class MultistoreFileTests(unittest.TestCase): + + def test_lock_file_raises_ioerror(self): + filehandle, filename = tempfile.mkstemp() + os.close(filehandle) + + try: + for error_code in (errno.EDEADLK, errno.ENOSYS, errno.ENOLCK): + multistore = multistore_file._MultiStore(filename) + multistore._file = _MockLockedFile(filename, error_code) + # Should not raise even though the underlying file class did. + multistore._lock() + self.assertTrue(multistore._file.open_and_lock_called) + finally: + os.unlink(filename)