Skip to content

Commit 8bacbc1

Browse files
authored
Merge pull request rust-lang#5073 from RalfJung/flock-tests
flock tests: cover the case of asking for both locks on the same file handle
2 parents 617db62 + 97f91eb commit 8bacbc1

2 files changed

Lines changed: 47 additions & 12 deletions

File tree

src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
//@ignore-target: android # Does not (always?) have flock
44
//@compile-flags: -Zmiri-disable-isolation
55

6+
//@revisions: windows_host unix_host
7+
//@[unix_host] ignore-host: windows
8+
//@[windows_host] only-host: windows
9+
610
use std::fs::File;
711
use std::os::fd::AsRawFd;
812

@@ -18,31 +22,31 @@ fn main() {
1822

1923
let files: Vec<File> = (0..3).map(|_| File::open(&path).unwrap()).collect();
2024

21-
// Test that we can apply many shared locks
25+
// Test that we can apply many shared locks.
2226
for file in files.iter() {
2327
errno_check(unsafe { libc::flock(file.as_raw_fd(), libc::LOCK_SH) });
2428
}
2529

26-
// Test that shared lock prevents exclusive lock
30+
// Test that shared lock prevents exclusive lock.
2731
{
2832
let fd = files[0].as_raw_fd();
2933
let err =
3034
errno_result(unsafe { libc::flock(fd, libc::LOCK_EX | libc::LOCK_NB) }).unwrap_err();
3135
assert_eq!(err.raw_os_error().unwrap(), libc::EWOULDBLOCK);
3236
}
3337

34-
// Unlock shared lock
38+
// Unlock shared lock.
3539
for file in files.iter() {
3640
errno_check(unsafe { libc::flock(file.as_raw_fd(), libc::LOCK_UN) });
3741
}
3842

39-
// Take exclusive lock
43+
// Take exclusive lock.
4044
{
4145
let fd = files[0].as_raw_fd();
4246
errno_check(unsafe { libc::flock(fd, libc::LOCK_EX) });
4347
}
4448

45-
// Test that shared lock prevents exclusive and shared locks
49+
// Test that exclusive lock prevents exclusive and shared locks.
4650
{
4751
let fd = files[1].as_raw_fd();
4852
let err =
@@ -55,9 +59,39 @@ fn main() {
5559
assert_eq!(err.raw_os_error().unwrap(), libc::EWOULDBLOCK);
5660
}
5761

58-
// Unlock exclusive lock
62+
// Unlock exclusive lock.
5963
{
6064
let fd = files[0].as_raw_fd();
6165
errno_check(unsafe { libc::flock(fd, libc::LOCK_UN) });
66+
// Redundant unlock also works.
67+
// FIXME(#miri/5074): except on Windows hosts...
68+
if !cfg!(windows_host) {
69+
errno_check(unsafe { libc::flock(fd, libc::LOCK_UN) });
70+
}
71+
}
72+
73+
// Test behavior when we acquire multiple locks on the same FD.
74+
// FIXME(#miri/5074): this does not behave correctly on Windows hosts.
75+
if !cfg!(windows_host) {
76+
let fd1 = files[1].as_raw_fd();
77+
let fd2 = files[2].as_raw_fd();
78+
79+
errno_check(unsafe { libc::flock(fd1, libc::LOCK_EX | libc::LOCK_NB) });
80+
// This converts the exclusive lock to a shared lock.
81+
errno_check(unsafe { libc::flock(fd1, libc::LOCK_SH | libc::LOCK_NB) });
82+
// Now the other fd can have the shared lock as well.
83+
errno_check(unsafe { libc::flock(fd2, libc::LOCK_SH | libc::LOCK_NB) });
84+
85+
// Reset.
86+
errno_check(unsafe { libc::flock(fd1, libc::LOCK_UN) });
87+
errno_check(unsafe { libc::flock(fd2, libc::LOCK_UN) });
88+
89+
// Getting first a shared lock and then upgrading to exclusive should also work.
90+
errno_check(unsafe { libc::flock(fd1, libc::LOCK_SH | libc::LOCK_NB) });
91+
errno_check(unsafe { libc::flock(fd1, libc::LOCK_EX | libc::LOCK_NB) });
92+
// This is truly exclusive: fd2 is locked out.
93+
let err =
94+
errno_result(unsafe { libc::flock(fd2, libc::LOCK_SH | libc::LOCK_NB) }).unwrap_err();
95+
assert_eq!(err.raw_os_error().unwrap(), libc::EWOULDBLOCK);
6296
}
6397
}

src/tools/miri/tests/pass/shims/fs.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -417,20 +417,21 @@ fn test_flock() {
417417
let file1 = OpenOptions::new().read(true).write(true).open(&path).unwrap();
418418
let file2 = OpenOptions::new().read(true).write(true).open(&path).unwrap();
419419

420-
// Test that we can apply many shared locks
420+
// Test that we can apply many shared locks.
421421
file1.lock_shared().unwrap();
422422
file2.lock_shared().unwrap();
423-
// Test that shared lock prevents exclusive lock
423+
// Test that shared lock prevents exclusive lock.
424424
assert!(matches!(file1.try_lock().unwrap_err(), fs::TryLockError::WouldBlock));
425-
// Unlock shared lock
425+
// Unlock both files.
426426
file1.unlock().unwrap();
427427
file2.unlock().unwrap();
428-
// Take exclusive lock
428+
429+
// Take exclusive lock.
429430
file1.lock().unwrap();
430-
// Test that shared lock prevents exclusive and shared locks
431+
// Test that shared lock prevents exclusive and shared locks.
431432
assert!(matches!(file2.try_lock().unwrap_err(), fs::TryLockError::WouldBlock));
432433
assert!(matches!(file2.try_lock_shared().unwrap_err(), fs::TryLockError::WouldBlock));
433-
// Unlock exclusive lock
434+
// Unlock exclusive lock.
434435
file1.unlock().unwrap();
435436
}
436437

0 commit comments

Comments
 (0)