Skip to content

Commit a2ff0e2

Browse files
Add some features to flock.
1 parent 7a92d0a commit a2ff0e2

File tree

2 files changed

+106
-22
lines changed

2 files changed

+106
-22
lines changed

src/librustc_data_structures/flock.rs

+105-21
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//! librustdoc, it is not production quality at all.
1616
1717
#![allow(non_camel_case_types)]
18+
use std::path::Path;
1819

1920
pub use self::imp::Lock;
2021

@@ -41,6 +42,7 @@ mod imp {
4142
pub l_sysid: libc::c_int,
4243
}
4344

45+
pub const F_RDLCK: libc::c_short = 0;
4446
pub const F_WRLCK: libc::c_short = 1;
4547
pub const F_UNLCK: libc::c_short = 2;
4648
pub const F_SETLK: libc::c_int = 6;
@@ -60,6 +62,7 @@ mod imp {
6062
pub l_sysid: libc::c_int,
6163
}
6264

65+
pub const F_RDLCK: libc::c_short = 1;
6366
pub const F_UNLCK: libc::c_short = 2;
6467
pub const F_WRLCK: libc::c_short = 3;
6568
pub const F_SETLK: libc::c_int = 12;
@@ -84,6 +87,7 @@ mod imp {
8487
pub l_sysid: libc::c_int,
8588
}
8689

90+
pub const F_RDLCK: libc::c_short = 1;
8791
pub const F_UNLCK: libc::c_short = 2;
8892
pub const F_WRLCK: libc::c_short = 3;
8993
pub const F_SETLK: libc::c_int = 8;
@@ -105,6 +109,7 @@ mod imp {
105109
pub l_sysid: libc::c_int,
106110
}
107111

112+
pub const F_RDLCK: libc::c_short = 1;
108113
pub const F_UNLCK: libc::c_short = 2;
109114
pub const F_WRLCK: libc::c_short = 3;
110115
pub const F_SETLK: libc::c_int = 8;
@@ -124,6 +129,7 @@ mod imp {
124129
pub l_pid: libc::pid_t,
125130
}
126131

132+
pub const F_RDLCK: libc::c_short = 1;
127133
pub const F_WRLCK: libc::c_short = 2;
128134
pub const F_UNLCK: libc::c_short = 3;
129135
pub const F_SETLK: libc::c_int = 6;
@@ -135,32 +141,53 @@ mod imp {
135141
}
136142

137143
impl Lock {
138-
pub fn new(p: &Path) -> Lock {
144+
pub fn new(p: &Path,
145+
wait: bool,
146+
create: bool,
147+
exclusive: bool)
148+
-> io::Result<Lock> {
139149
let os: &OsStr = p.as_ref();
140150
let buf = CString::new(os.as_bytes()).unwrap();
151+
let open_flags = if create {
152+
libc::O_RDWR | libc::O_CREAT
153+
} else {
154+
libc::O_RDWR
155+
};
156+
141157
let fd = unsafe {
142-
libc::open(buf.as_ptr(), libc::O_RDWR | libc::O_CREAT,
158+
libc::open(buf.as_ptr(), open_flags,
143159
libc::S_IRWXU as libc::c_int)
144160
};
145-
assert!(fd > 0, "failed to open lockfile: {}",
146-
io::Error::last_os_error());
161+
162+
if fd < 0 {
163+
return Err(io::Error::last_os_error());
164+
}
165+
166+
let lock_type = if exclusive {
167+
os::F_WRLCK
168+
} else {
169+
os::F_RDLCK
170+
};
171+
147172
let flock = os::flock {
148173
l_start: 0,
149174
l_len: 0,
150175
l_pid: 0,
151176
l_whence: libc::SEEK_SET as libc::c_short,
152-
l_type: os::F_WRLCK,
177+
l_type: lock_type,
153178
l_sysid: 0,
154179
};
180+
let cmd = if wait { os::F_SETLKW } else { os::F_SETLK };
155181
let ret = unsafe {
156-
libc::fcntl(fd, os::F_SETLKW, &flock)
182+
libc::fcntl(fd, cmd, &flock)
157183
};
158184
if ret == -1 {
159185
let err = io::Error::last_os_error();
160186
unsafe { libc::close(fd); }
161-
panic!("could not lock `{}`: {}", p.display(), err);
187+
Err(err)
188+
} else {
189+
Ok(Lock { fd: fd })
162190
}
163-
Lock { fd: fd }
164191
}
165192
}
166193

@@ -191,18 +218,28 @@ mod imp {
191218
use std::os::windows::raw::HANDLE;
192219
use std::path::Path;
193220
use std::fs::{File, OpenOptions};
221+
use std::os::raw::{c_ulong, c_ulonglong, c_int};
222+
use std::os::windows::fs::OpenOptionsExt;
223+
224+
pub type DWORD = c_ulong;
225+
pub type BOOL = c_int;
226+
pub type ULONG_PTR = c_ulonglong;
194227

195-
type DWORD = u32;
196228
type LPOVERLAPPED = *mut OVERLAPPED;
197-
type BOOL = i32;
198229
const LOCKFILE_EXCLUSIVE_LOCK: DWORD = 0x00000002;
230+
const LOCKFILE_FAIL_IMMEDIATELY: DWORD = 0x00000001;
231+
232+
pub const FILE_SHARE_DELETE: DWORD = 0x4;
233+
pub const FILE_SHARE_READ: DWORD = 0x1;
234+
pub const FILE_SHARE_WRITE: DWORD = 0x2;
199235

200236
#[repr(C)]
201237
struct OVERLAPPED {
202-
Internal: usize,
203-
InternalHigh: usize,
204-
Pointer: *mut u8,
205-
hEvent: *mut u8,
238+
Internal: ULONG_PTR,
239+
InternalHigh: ULONG_PTR,
240+
Offset: DWORD,
241+
OffsetHigh: DWORD,
242+
hEvent: HANDLE,
206243
}
207244

208245
extern "system" {
@@ -219,19 +256,66 @@ mod imp {
219256
}
220257

221258
impl Lock {
222-
pub fn new(p: &Path) -> Lock {
223-
let f = OpenOptions::new().read(true).write(true).create(true)
224-
.open(p).unwrap();
259+
pub fn new(p: &Path,
260+
wait: bool,
261+
create: bool,
262+
exclusive: bool)
263+
-> io::Result<Lock> {
264+
265+
let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;
266+
267+
let f = {
268+
let mut open_options = OpenOptions::new().read(true)
269+
.share_mode(share_mode);
270+
if create {
271+
open_options.create(true);
272+
}
273+
274+
match open_options.open(p) {
275+
Ok(file) => file,
276+
Err(err) => return Err(err),
277+
}
278+
};
279+
225280
let ret = unsafe {
226281
let mut overlapped: OVERLAPPED = mem::zeroed();
227-
LockFileEx(f.as_raw_handle(), LOCKFILE_EXCLUSIVE_LOCK, 0, 100, 0,
282+
283+
let mut dwFlags = 0;
284+
if !wait {
285+
dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
286+
}
287+
288+
if exclusive {
289+
dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
290+
}
291+
292+
LockFileEx(f.as_raw_handle(),
293+
dwFlags,
294+
0,
295+
0xFFFF_FFFF,
296+
0xFFFF_FFFF,
228297
&mut overlapped)
229298
};
230299
if ret == 0 {
231-
let err = io::Error::last_os_error();
232-
panic!("could not lock `{}`: {}", p.display(), err);
300+
Err(io::Error::last_os_error())
301+
} else {
302+
Ok(Lock { _file: f })
233303
}
234-
Lock { _file: f }
235304
}
236305
}
306+
307+
// Note that we don't need a Drop impl on the Windows: The file is unlocked
308+
// automatically when it's closed.
309+
}
310+
311+
impl imp::Lock {
312+
pub fn panicking_new(p: &Path,
313+
wait: bool,
314+
create: bool,
315+
exclusive: bool)
316+
-> Lock {
317+
Lock::new(p, wait, create, exclusive).unwrap_or_else(|err| {
318+
panic!("could not lock `{}`: {}", p.display(), err);
319+
})
320+
}
237321
}

src/librustdoc/html/render.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ fn write_shared(cx: &Context,
651651
// docs placed in the output directory, so this needs to be a synchronized
652652
// operation with respect to all other rustdocs running around.
653653
try_err!(mkdir(&cx.dst), &cx.dst);
654-
let _lock = flock::Lock::new(&cx.dst.join(".lock"));
654+
let _lock = flock::Lock::panicking_new(&cx.dst.join(".lock"), true, true, true);
655655

656656
// Add all the static files. These may already exist, but we just
657657
// overwrite them anyway to make sure that they're fresh and up-to-date.

0 commit comments

Comments
 (0)