Skip to content

Comments

added basic file locking capabilities for unix and windows#285

Merged
jonasmalacofilho merged 31 commits intomasterfrom
274-keyval-file-locking
Feb 17, 2021
Merged

added basic file locking capabilities for unix and windows#285
jonasmalacofilho merged 31 commits intomasterfrom
274-keyval-file-locking

Conversation

@MarshallAsch
Copy link
Member

@MarshallAsch MarshallAsch commented Feb 9, 2021

Closes #274

This should solve issues with multiple instances of liquidctl running at the same time having issues with concurrent access of the data file.

This is being resolved by using lock files to make the functions for the RuntimeStorage class atomic.

Also adds the function load_store() which can get a value, update it and then save it atomically.

  • write tests to validate that the calls are atomic
  • write tests to validate that multiple load()'s can happen at the same time
  • update all usages to use the atomic load_store function where applicable

There may be an issue on windows that if the program crashes before the lock file can be deleted it will not be able to acquire the lock again, and the program will hang.

@jonasmalacofilho jonasmalacofilho added the blocking Blocks a current release label Feb 11, 2021
@MarshallAsch MarshallAsch marked this pull request as ready for review February 14, 2021 03:09
MarshallAsch and others added 22 commits February 14, 2021 22:45
Windows file locking will have an issue where if the program crashes before the lock file gets deleted the program will be blocked
…ded a couple lines back in that accidentally got removed
This reverts commit 409869b ("made change to make it work on the
mac pipelines"), as it was broken (missing `assert` keywords effectively
disables the assertions) and only introduced unreachable changes (typo
in `dawrin` prevents any existing platform to enter those branches).

It is also notable that Mac OS and Linux behaviors only deviate in a
single test.  If the reverted commit had worked as intended, it would
have *broken* two other tests.
This makes all tests that depend on runtime storage more robust.

Mocking the entire API allowed it to be get out of sync with the real
implementation, and is not necessary in this (simple) case.
Copy link
Member Author

@MarshallAsch MarshallAsch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aside from the comments I don't immediately spot any major issues,

class MockRuntimeStorage(RuntimeStorage):
def __init__(self, key_prefixes, backend=None):
if not backend:
run_dir = mkdtemp('run_dir')
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this use the pytest tempdir utility?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have preferred to use it, yes. But I couldn't figure out how to use the magic tempdir fixture within an arbitrary class. Do you know how it can be done?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose it could be passed in, but that is a but gross.

def __init__(self, key_prefixes):
self._backend = _FilesystemBackend(key_prefixes)
def __init__(self, key_prefixes, backend=None):
self._backend = backend if backend is not None else _FilesystemBackend(key_prefixes)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Self nitpick: this could be written in a more clear way.

Also, should be accept runtime_dirs instead of requiring the tests to construct a private _FilesystemBackend class? This would also avoid having the tests pass key_prefixes both to the backend and to the RuntimeStorage wrapper.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo passing a backend to the test could make sense because it would allow us to swap it out with a mock to speed up the driver tests instead of writing to the disk, (which from what my understanding was is best practice anyway?)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We used to mock the backend without any actual FS access, but in this branch I actually made all tests revert back to a real FS backend, albeit with temporary and isolated locations.

Using a mocked backend requires keeping it in sync with the real implementation, something we weren't great at. And that extra work and risk for a small performance improvement in our test suite is just not worth it, IMO.

@jonasmalacofilho jonasmalacofilho merged commit 8d1e5dd into master Feb 17, 2021
@jonasmalacofilho jonasmalacofilho deleted the 274-keyval-file-locking branch March 7, 2021 02:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

blocking Blocks a current release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Running two liquidctl processes causes Corsair H100i PRO XT to stop responding to read requests.

2 participants