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

feat: flock db dir #500

Merged
merged 1 commit into from
Oct 21, 2024
Merged

feat: flock db dir #500

merged 1 commit into from
Oct 21, 2024

Conversation

pepyakin
Copy link
Contributor

@pepyakin pepyakin commented Oct 21, 2024

Closes #483

This commit aim is to return an error message if another process tries
to use the same db directory, which is unsupported according to our
assumptions.

Note that this uses only advisory locking. It's still possible to mess
with the directory and containing files. It's the responsibility of the
user to prevent that and failure to do so can and will lead to
unexpected behavior.

Implementation Notes

A couple of words on my research of the problem and the taken approach.

There are mandatory and advisory locking. Mandatory locking is a feature of OS that reserves an exclusive right for a specific program to access a particular file. On Linux, mandatory locking is turned off by default and to be avoided (see this). macOS doesn't support mandatory locking.

The typical way to solve this issue is to use advisory locking. That is, depend on the cooperation between the processes that use the files and directories in question. Obviously, this depends on a good will of those processes and not a ironclad solution.

On Linux, it's possible to lock a directory. flock with the fd of the directory open with O_PATH can be used. macOS doesn't support opening fds with O_PATH, so this option is not available. To make the solution cross-platform, I stuck to creating a lock file named .lock in the DB directory and obtaining an exclusive lock on that.

Now, the original TODO and issue (#483) mentions the TOCTOU issues. Namely, the fact that the checking if the db directory exists, opening the db dir, initializing the db, opening the db files are all non-atomic and it's possible that the state of the filesystem has changed between the checks and file opening or creation, which can lead to all sorts of issues.

Proper implementation should probably employ openat family of syscalls to avoid some of those, at least on Linux. This all is out-of-scope for this PR and better be addressed on the next big refactoring in one fell swoop, e.g. with #501.

Copy link
Contributor Author

pepyakin commented Oct 21, 2024

This stack of pull requests is managed by Graphite. Learn more about stacking.

Join @pepyakin and the rest of your teammates on Graphite Graphite

@pepyakin pepyakin changed the base branch from pep-feat-configurable-rollback-tp-size to pep-chore-fix-macos-build October 21, 2024 13:36
@pepyakin pepyakin mentioned this pull request Oct 21, 2024
@@ -29,6 +29,7 @@ lru = "0.12.3"
libc = "0.2.155"
criterion = { version = "0.3", optional = true }
thread_local = "1.1.8"
fs2 = "0.4.3"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is not my favorite, as this doesn't give us much. We don't care about supporting much besides modern Linux and macOS, we don't explicitly target Windows and can just directly use flock. But I thought for now this is OK and we should reconsider that in #501.

impl Drop for Flock {
fn drop(&mut self) {
if let Err(e) = self.lock_fd.unlock() {
eprintln!("Failed to unlock directory lock: {e}");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I know this is the first appearance of eprintln! in this codebase. Should we finally add tracing or log? Or should we just swallow this error? Or leave it as is for now?

Copy link
Contributor

Choose a reason for hiding this comment

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

This should really only happen very rarely. An eprintln! seems fine, and it'd at least give an indication of what went wrong that can come back up to us.

@pepyakin pepyakin marked this pull request as ready for review October 21, 2024 14:20
Copy link
Contributor Author

pepyakin commented Oct 21, 2024

Merge activity

  • Oct 21, 12:26 PM EDT: A user started a stack merge that includes this pull request via Graphite.
  • Oct 21, 12:28 PM EDT: Graphite rebased this pull request as part of a merge.
  • Oct 21, 12:29 PM EDT: A user merged this pull request with Graphite.

Base automatically changed from pep-chore-fix-macos-build to master October 21, 2024 16:26
Closes #483

This commit aim is to return an error message if another process tries
to use the same db directory, which is unsupported according to our
assumptions.

Note that this uses only advisory locking. It's still possible to mess
with the directory and containing files. It's the responsibility of the
user to prevent that and failure to do so can and will lead to
unexpected behavior.
@pepyakin pepyakin merged commit e16ded5 into master Oct 21, 2024
2 checks passed
@pepyakin pepyakin deleted the pep-flock branch October 21, 2024 16:29
pepyakin added a commit that referenced this pull request Nov 5, 2024
fs2 was introduced in PR #500, but we actually don't really need that
much from it. This commit removes the extra dependency in favor of doing
the same directly. I think this is pretty-much equivalent to inlining
the code.
@pepyakin pepyakin mentioned this pull request Nov 5, 2024
pepyakin added a commit that referenced this pull request Nov 5, 2024
fs2 was introduced in PR #500, but we actually don't really need that
much from it. This commit removes the extra dependency in favor of doing
the same directly. I think this is pretty-much equivalent to inlining
the code.
pepyakin added a commit that referenced this pull request Nov 5, 2024
fs2 was introduced in PR #500, but we actually don't really need that
much from it. This commit removes the extra dependency in favor of doing
the same directly. I think this is pretty-much equivalent to inlining
the code.
pepyakin added a commit that referenced this pull request Nov 5, 2024
fs2 was introduced in PR #500, but we actually don't really need that
much from it. This commit removes the extra dependency in favor of doing
the same directly. I think this is pretty-much equivalent to inlining
the code.
rphmeier pushed a commit that referenced this pull request Nov 5, 2024
fs2 was introduced in PR #500, but we actually don't really need that
much from it. This commit removes the extra dependency in favor of doing
the same directly. I think this is pretty-much equivalent to inlining
the code.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Obtain exclusive lock for db dir
2 participants