Skip to content

Avoid file lock warning for in-process contention#1406

Merged
j178 merged 2 commits intomasterfrom
lock-warning
Jan 19, 2026
Merged

Avoid file lock warning for in-process contention#1406
j178 merged 2 commits intomasterfrom
lock-warning

Conversation

@j178
Copy link
Owner

@j178 j178 commented Jan 19, 2026

Follow up for #1353

@j178 j178 added the bug Something isn't working label Jan 19, 2026
@j178 j178 changed the title lock warning Avoid file lock warning for in-process contention Jan 19, 2026
@codecov
Copy link

codecov bot commented Jan 19, 2026

Codecov Report

❌ Patch coverage is 91.11111% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.39%. Comparing base (ac1b1d4) to head (98d4fcf).
⚠️ Report is 6 commits behind head on master.

Files with missing lines Patch % Lines
crates/prek/src/fs.rs 91.01% 8 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1406   +/-   ##
=======================================
  Coverage   90.38%   90.39%           
=======================================
  Files          82       82           
  Lines       16208    16262   +54     
=======================================
+ Hits        14650    14700   +50     
- Misses       1558     1562    +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions
Copy link

github-actions bot commented Jan 19, 2026

📦 Cargo Bloat Comparison

Binary size change: +0.00% (22.5 MiB → 22.5 MiB)

Expand for cargo-bloat output

Head Branch Results

 File  .text    Size        Crate Name
 0.3%   0.8% 71.7KiB        prek? <prek::cli::Command as clap_builder::derive::Subcommand>::augment_subcommands
 0.2%   0.6% 54.6KiB         prek prek::languages::<impl prek::config::Language>::run::{{closure}}::{{closure}}
 0.2%   0.5% 49.8KiB         prek prek::languages::<impl prek::config::Language>::run::{{closure}}::{{closure}}
 0.2%   0.5% 46.3KiB         prek prek::run::{{closure}}
 0.2%   0.5% 42.7KiB         prek prek::identify::by_extension::{{closure}}
 0.2%   0.5% 42.6KiB         prek prek::cli::run::run::run::{{closure}}
 0.2%   0.4% 35.1KiB         prek prek::languages::<impl prek::config::Language>::install::{{closure}}
 0.1%   0.3% 32.0KiB        prek? <prek::cli::RunArgs as clap_builder::derive::Args>::augment_args
 0.1%   0.3% 30.0KiB  serde_json? <&mut serde_json::de::Deserializer<R> as serde_core::de::Deserializer>::deserialize_struct
 0.1%   0.2% 21.5KiB         prek prek::archive::unzip::{{closure}}
 0.1%   0.2% 21.3KiB clap_builder clap_builder::parser::parser::Parser::get_matches_with
 0.1%   0.2% 21.0KiB         prek prek::hooks::meta_hooks::MetaHooks::run::{{closure}}
 0.1%   0.2% 20.8KiB         prek prek::hooks::meta_hooks::MetaHooks::run::{{closure}}
 0.1%   0.2% 19.6KiB         prek <prek::languages::ruby::ruby::Ruby as prek::languages::LanguageImpl>::install::{{closure}}
 0.1%   0.2% 19.3KiB         prek prek::cli::run::filter::collect_files_from_args::{{closure}}
 0.1%   0.2% 18.9KiB         prek prek::cli::run::filter::collect_files_from_args::{{closure}}
 0.1%   0.2% 18.6KiB         ring ring_core_0_17_14__x25519_ge_frombytes_vartime
 0.1%   0.2% 18.2KiB   hyper_util hyper_util::client::legacy::client::Client<C,B>::send_request::{{closure}}
 0.1%   0.2% 18.1KiB    [Unknown] fe_loose_invert
 0.1%   0.2% 17.7KiB         prek prek::cli::run::filter::collect_files_from_args::{{closure}}
36.7%  91.6%  8.2MiB              And 19817 smaller methods. Use -n N to show more.
40.0% 100.0%  9.0MiB              .text section size, the file size is 22.5MiB

Base Branch Results

 File  .text    Size        Crate Name
 0.3%   0.8% 71.2KiB        prek? <prek::cli::Command as clap_builder::derive::Subcommand>::augment_subcommands
 0.2%   0.6% 53.8KiB         prek prek::languages::<impl prek::config::Language>::run::{{closure}}::{{closure}}
 0.2%   0.5% 49.8KiB         prek prek::languages::<impl prek::config::Language>::run::{{closure}}::{{closure}}
 0.2%   0.5% 46.2KiB         prek prek::run::{{closure}}
 0.2%   0.5% 42.5KiB         prek prek::cli::run::run::run::{{closure}}
 0.2%   0.4% 35.1KiB         prek prek::languages::<impl prek::config::Language>::install::{{closure}}
 0.1%   0.3% 31.6KiB        prek? <prek::cli::RunArgs as clap_builder::derive::Args>::augment_args
 0.1%   0.3% 30.0KiB  serde_json? <&mut serde_json::de::Deserializer<R> as serde_core::de::Deserializer>::deserialize_struct
 0.1%   0.3% 27.6KiB         prek prek::identify::by_extension::{{closure}}
 0.1%   0.2% 21.5KiB         prek prek::archive::unzip::{{closure}}
 0.1%   0.2% 21.3KiB clap_builder clap_builder::parser::parser::Parser::get_matches_with
 0.1%   0.2% 21.0KiB         prek prek::hooks::meta_hooks::MetaHooks::run::{{closure}}
 0.1%   0.2% 20.8KiB         prek prek::hooks::meta_hooks::MetaHooks::run::{{closure}}
 0.1%   0.2% 19.6KiB         prek <prek::languages::ruby::ruby::Ruby as prek::languages::LanguageImpl>::install::{{closure}}
 0.1%   0.2% 19.2KiB         prek prek::cli::run::filter::collect_files_from_args::{{closure}}
 0.1%   0.2% 18.9KiB         prek prek::cli::run::filter::collect_files_from_args::{{closure}}
 0.1%   0.2% 18.6KiB         ring ring_core_0_17_14__x25519_ge_frombytes_vartime
 0.1%   0.2% 18.2KiB   hyper_util hyper_util::client::legacy::client::Client<C,B>::send_request::{{closure}}
 0.1%   0.2% 18.1KiB    [Unknown] fe_loose_invert
 0.1%   0.2% 17.7KiB         prek prek::cli::run::filter::collect_files_from_args::{{closure}}
36.7%  91.8%  8.2MiB              And 19756 smaller methods. Use -n N to show more.
40.0% 100.0%  9.0MiB              .text section size, the file size is 22.5MiB

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request improves the file lock contention detection logic to avoid showing spurious warnings when lock contention occurs within the same process. It adds reference counting to track which locks are held by the current process and suppresses the "Another prek process may still be running" warning for in-process contention.

Changes:

  • Added reference counting mechanism (IN_PROCESS_LOCK_HELD_COUNTS) to track locks held by the current process
  • Modified LockedFile to store the lock path and maintain reference counts on acquire/release
  • Updated warning logic to check if lock is held in-process before showing cross-process warning
  • Refactored test infrastructure with new test-only globals (LOCK_WARNING_PATHS, FORCE_CROSS_PROCESS_LOCK_WARNING_FOR)
  • Improved user-facing message in reporter from "Initializing hooks..." to "Cloning repos..."

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
crates/prek/src/fs.rs Implements in-process lock tracking with reference counting and updates warning logic; includes refactored tests
crates/prek/src/cli/reporter.rs Updates progress message from "Initializing hooks..." to "Cloning repos..." for better clarity

}

impl LockedFile {
/// Inner implementation for [`LockedFile::acquire_blocking`] and [`LockedFile::acquire`].
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

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

The comment references LockedFile::acquire_blocking, but this method does not exist in the codebase. The lock_file_blocking method is now a private helper that only returns Result<fs_err::File, std::io::Error>, not a LockedFile. Update the comment to accurately reflect the current implementation, or remove the reference to acquire_blocking if it's no longer part of the public API.

Suggested change
/// Inner implementation for [`LockedFile::acquire_blocking`] and [`LockedFile::acquire`].
/// Helper to acquire an exclusive lock on a file, blocking if necessary.

Copilot uses AI. Check for mistakes.
Comment on lines +177 to 192
if let Err(err) = self.file.file().unlock() {
error!(
"Failed to unlock {}; program may be stuck: {}",
self.0.path().display(),
self.file.path().display(),
err
);
} else {
trace!(path = %self.0.path().display(), "Released lock");
let mut held = IN_PROCESS_LOCK_HELD_COUNTS.lock().unwrap();
if let Some(count) = held.get_mut(&self.path) {
*count = count.saturating_sub(1);
if *count == 0 {
held.remove(&self.path);
}
}
trace!(path = %self.file.path().display(), "Released lock");
}
Copy link

Copilot AI Jan 19, 2026

Choose a reason for hiding this comment

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

The reference count is only decremented when the unlock operation succeeds (inside the else block). If unlock() fails, the count remains incremented, which will cause future lock contention on the same path to incorrectly believe the lock is still held by this process, suppressing warnings that should be shown.

The count should be decremented regardless of whether the unlock succeeds or fails, since the LockedFile is being dropped and will no longer hold the lock from the application's perspective. Move the count decrement logic (lines 184-190) outside of the if-else statement so it always executes.

Copilot uses AI. Check for mistakes.
@j178 j178 merged commit e9716ae into master Jan 19, 2026
22 checks passed
@j178 j178 deleted the lock-warning branch January 19, 2026 07:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant