Skip to content

Commit

Permalink
rustc: Handle concurrent create_dir requests
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
alexcrichton committed May 2, 2016
1 parent 855fb61 commit 71e6329
Showing 1 changed file with 24 additions and 2 deletions.
26 changes: 24 additions & 2 deletions src/librustc_incremental/persist/util.rs
Expand Up @@ -9,14 +9,16 @@
// except according to those terms.

use rustc::ty;

use std::fs;
use std::path::PathBuf;
use std::io;
use std::path::{PathBuf, Path};

pub fn dep_graph_path<'tcx>(tcx: &ty::TyCtxt<'tcx>) -> Option<PathBuf> {
// For now, just save/load dep-graph from
// directory/dep_graph.rbml
tcx.sess.opts.incremental.as_ref().and_then(|incr_dir| {
match fs::create_dir_all(&incr_dir){
match create_dir_racy(&incr_dir) {
Ok(()) => {}
Err(err) => {
tcx.sess.err(
Expand All @@ -30,3 +32,23 @@ pub fn dep_graph_path<'tcx>(tcx: &ty::TyCtxt<'tcx>) -> Option<PathBuf> {
})
}

// Like std::fs::create_dir_all, except handles concurrent calls among multiple
// threads or processes.
fn create_dir_racy(path: &Path) -> io::Result<()> {
match fs::create_dir(path) {
Ok(()) => return Ok(()),
Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => return Ok(()),
Err(ref e) if e.kind() == io::ErrorKind::NotFound => {}
Err(e) => return Err(e),
}
match path.parent() {
Some(p) => try!(create_dir_racy(p)),
None => return Err(io::Error::new(io::ErrorKind::Other,
"failed to create whole tree")),
}
match fs::create_dir(path) {
Ok(()) => Ok(()),
Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => Ok(()),
Err(e) => Err(e),
}
}

0 comments on commit 71e6329

Please sign in to comment.