Skip to content

Commit 030aac5

Browse files
committed
fix: per-toolchain installation lock
1 parent 1c9262c commit 030aac5

File tree

5 files changed

+35
-6
lines changed

5 files changed

+35
-6
lines changed

Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/elan-dist/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ json = "0.12.4"
2626
zip = "0.6"
2727
filetime = "0.2.14"
2828
time = "0.3"
29+
fslock = "0.2.1"
2930

3031
[target."cfg(windows)".dependencies]
3132
winapi = { version = "0.3.9", features = ["handleapi", "sysinfoapi", "tlhelp32", "winnt"] }
@@ -36,4 +37,3 @@ libc = "0.2.88"
3637

3738
[lib]
3839
name = "elan_dist"
39-

src/elan-dist/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![recursion_limit = "1024"]
22

3+
extern crate fslock;
34
extern crate elan_utils;
45
extern crate flate2;
56
extern crate itertools;

src/elan-dist/src/manifestation.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
//! Manifest a particular Lean version by installing it from a distribution server.
22
3+
use std::{thread::sleep, time::Duration};
4+
35
use component::{TarGzPackage, TarZstdPackage, ZipPackage};
46
use download::DownloadCfg;
5-
use elan_utils::utils;
7+
use elan_utils::{raw::read_file, utils};
68
use errors::*;
9+
use fslock::LockFile;
710
use notifications::*;
811
use prefix::InstallPrefix;
912
use temp;
@@ -25,11 +28,23 @@ impl Manifestation {
2528
temp_cfg: &temp::Cfg,
2629
notify_handler: &dyn Fn(Notification),
2730
) -> Result<()> {
31+
let lockfile_path = self.prefix.path().with_extension("lock");
32+
let mut lockfile = LockFile::open(&lockfile_path)?;
33+
if !lockfile.try_lock_with_pid()? {
34+
notify_handler(Notification::WaitingForFileLock(&lockfile_path, read_file(&lockfile_path)?.trim()));
35+
while !lockfile.try_lock_with_pid()? {
36+
sleep(Duration::from_secs(1));
37+
}
38+
}
2839
let dlcfg = DownloadCfg {
2940
temp_cfg: temp_cfg,
3041
notify_handler: notify_handler,
3142
};
3243

44+
if utils::is_directory(self.prefix.path()) {
45+
return Ok(())
46+
}
47+
3348
// find correct download on HTML page (AAAAH)
3449
use regex::Regex;
3550
use std::fs;
@@ -77,10 +92,6 @@ impl Manifestation {
7792
// unpack into temporary place, then move atomically to guard against aborts during unpacking
7893
let unpack_dir = prefix.with_extension("tmp");
7994

80-
if utils::is_directory(prefix) {
81-
return Err(format!("'{}' is already installed", prefix.display()).into());
82-
}
83-
8495
if utils::is_directory(&unpack_dir) {
8596
utils::remove_dir("temp toolchain directory", &unpack_dir, &|n| {
8697
(notify_handler)(n.into())
@@ -103,6 +114,7 @@ impl Manifestation {
103114
}
104115

105116
utils::rename_dir("temp toolchain directory", &unpack_dir, prefix)?;
117+
let _ = std::fs::remove_file(&lockfile_path);
106118

107119
Ok(())
108120
}

src/elan-dist/src/notifications.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub enum Notification<'a> {
3131
DownloadingLegacyManifest,
3232
ManifestChecksumFailedHack,
3333
NewVersionAvailable(String),
34+
WaitingForFileLock(&'a Path, &'a str),
3435
}
3536

3637
impl<'a> From<elan_utils::Notification<'a>> for Notification<'a> {
@@ -65,6 +66,7 @@ impl<'a> Notification<'a> {
6566
| RollingBack
6667
| DownloadingManifest(_)
6768
| NewVersionAvailable(_)
69+
| WaitingForFileLock(_, _)
6870
| DownloadedManifest(_, _) => NotificationLevel::Info,
6971
CantReadUpdateHash(_)
7072
| ExtensionNotInstalled(_)
@@ -125,6 +127,9 @@ impl<'a> Display for Notification<'a> {
125127
"Version {version} of elan is available! Use `elan self update` to update."
126128
)
127129
}
130+
WaitingForFileLock(path, pid) => {
131+
write!(f, "waiting for previous installation request to finish ({}, held by PID {})", path.display(), pid)
132+
}
128133
}
129134
}
130135
}

0 commit comments

Comments
 (0)