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+
610use std:: fs:: File ;
711use 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}
0 commit comments