Skip to content

Commit 71e6329

Browse files
committed
rustc: Handle concurrent create_dir requests
The compiler created a directory as part of `-Z incremental` but that may be hierarchically used concurrently so we need to protect ourselves against that.
1 parent 855fb61 commit 71e6329

File tree

1 file changed

+24
-2
lines changed
  • src/librustc_incremental/persist

1 file changed

+24
-2
lines changed

src/librustc_incremental/persist/util.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@
99
// except according to those terms.
1010

1111
use rustc::ty;
12+
1213
use std::fs;
13-
use std::path::PathBuf;
14+
use std::io;
15+
use std::path::{PathBuf, Path};
1416

1517
pub fn dep_graph_path<'tcx>(tcx: &ty::TyCtxt<'tcx>) -> Option<PathBuf> {
1618
// For now, just save/load dep-graph from
1719
// directory/dep_graph.rbml
1820
tcx.sess.opts.incremental.as_ref().and_then(|incr_dir| {
19-
match fs::create_dir_all(&incr_dir){
21+
match create_dir_racy(&incr_dir) {
2022
Ok(()) => {}
2123
Err(err) => {
2224
tcx.sess.err(
@@ -30,3 +32,23 @@ pub fn dep_graph_path<'tcx>(tcx: &ty::TyCtxt<'tcx>) -> Option<PathBuf> {
3032
})
3133
}
3234

35+
// Like std::fs::create_dir_all, except handles concurrent calls among multiple
36+
// threads or processes.
37+
fn create_dir_racy(path: &Path) -> io::Result<()> {
38+
match fs::create_dir(path) {
39+
Ok(()) => return Ok(()),
40+
Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => return Ok(()),
41+
Err(ref e) if e.kind() == io::ErrorKind::NotFound => {}
42+
Err(e) => return Err(e),
43+
}
44+
match path.parent() {
45+
Some(p) => try!(create_dir_racy(p)),
46+
None => return Err(io::Error::new(io::ErrorKind::Other,
47+
"failed to create whole tree")),
48+
}
49+
match fs::create_dir(path) {
50+
Ok(()) => Ok(()),
51+
Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => Ok(()),
52+
Err(e) => Err(e),
53+
}
54+
}

0 commit comments

Comments
 (0)