Skip to content

Commit 074d667

Browse files
committed
Don't panic when failing to initialize incremental directory.
1 parent cdbe288 commit 074d667

File tree

7 files changed

+49
-27
lines changed

7 files changed

+49
-27
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3876,6 +3876,7 @@ dependencies = [
38763876
"rand 0.7.3",
38773877
"rustc_ast",
38783878
"rustc_data_structures",
3879+
"rustc_errors",
38793880
"rustc_fs_util",
38803881
"rustc_graphviz",
38813882
"rustc_hir",

compiler/rustc_data_structures/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ tempfile = "3.2"
3434
version = "0.11"
3535

3636
[target.'cfg(windows)'.dependencies]
37-
winapi = { version = "0.3", features = ["fileapi", "psapi"] }
37+
winapi = { version = "0.3", features = ["fileapi", "psapi", "winerror"] }
3838

3939
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
4040
memmap2 = "0.2.1"

compiler/rustc_data_structures/src/flock.rs

+13
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ cfg_if! {
5454
Ok(Lock { _file: file })
5555
}
5656
}
57+
58+
pub fn error_unsupported(err: &io::Error) -> bool {
59+
matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS))
60+
}
5761
}
5862

5963
// Note that we don't need a Drop impl to execute `flock(fd, LOCK_UN)`. Lock acquired by
@@ -103,6 +107,10 @@ cfg_if! {
103107
Ok(Lock { file })
104108
}
105109
}
110+
111+
pub fn error_unsupported(err: &io::Error) -> bool {
112+
matches!(err.raw_os_error(), Some(libc::ENOTSUP) | Some(libc::ENOSYS))
113+
}
106114
}
107115

108116
impl Drop for Lock {
@@ -122,6 +130,7 @@ cfg_if! {
122130
use std::mem;
123131
use std::os::windows::prelude::*;
124132

133+
use winapi::shared::winerror::ERROR_INVALID_FUNCTION;
125134
use winapi::um::minwinbase::{OVERLAPPED, LOCKFILE_FAIL_IMMEDIATELY, LOCKFILE_EXCLUSIVE_LOCK};
126135
use winapi::um::fileapi::LockFileEx;
127136
use winapi::um::winnt::{FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE};
@@ -194,6 +203,10 @@ cfg_if! {
194203
Ok(Lock { _file: file })
195204
}
196205
}
206+
207+
pub fn error_unsupported(err: &io::Error) -> bool {
208+
err.raw_os_error() == Some(ERROR_INVALID_FUNCTION as i32)
209+
}
197210
}
198211

199212
// Note that we don't need a Drop impl on the Windows: The file is unlocked

compiler/rustc_incremental/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ rustc_macros = { path = "../rustc_macros" }
2020
rustc_span = { path = "../rustc_span" }
2121
rustc_fs_util = { path = "../rustc_fs_util" }
2222
rustc_session = { path = "../rustc_session" }
23+
rustc_errors = { path = "../rustc_errors" }

compiler/rustc_incremental/src/persist/fs.rs

+30-23
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@
106106
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
107107
use rustc_data_structures::svh::Svh;
108108
use rustc_data_structures::{base_n, flock};
109+
use rustc_errors::ErrorReported;
109110
use rustc_fs_util::{link_or_copy, LinkOrCopy};
110111
use rustc_session::{CrateDisambiguator, Session};
111112

@@ -189,9 +190,9 @@ pub fn prepare_session_directory(
189190
sess: &Session,
190191
crate_name: &str,
191192
crate_disambiguator: CrateDisambiguator,
192-
) {
193+
) -> Result<(), ErrorReported> {
193194
if sess.opts.incremental.is_none() {
194-
return;
195+
return Ok(());
195196
}
196197

197198
let _timer = sess.timer("incr_comp_prepare_session_directory");
@@ -201,9 +202,7 @@ pub fn prepare_session_directory(
201202
// {incr-comp-dir}/{crate-name-and-disambiguator}
202203
let crate_dir = crate_path(sess, crate_name, crate_disambiguator);
203204
debug!("crate-dir: {}", crate_dir.display());
204-
if create_dir(sess, &crate_dir, "crate").is_err() {
205-
return;
206-
}
205+
create_dir(sess, &crate_dir, "crate")?;
207206

208207
// Hack: canonicalize the path *after creating the directory*
209208
// because, on windows, long paths can cause problems;
@@ -217,7 +216,7 @@ pub fn prepare_session_directory(
217216
crate_dir.display(),
218217
err
219218
));
220-
return;
219+
return Err(ErrorReported);
221220
}
222221
};
223222

@@ -232,16 +231,11 @@ pub fn prepare_session_directory(
232231

233232
// Lock the new session directory. If this fails, return an
234233
// error without retrying
235-
let (directory_lock, lock_file_path) = match lock_directory(sess, &session_dir) {
236-
Ok(e) => e,
237-
Err(_) => return,
238-
};
234+
let (directory_lock, lock_file_path) = lock_directory(sess, &session_dir)?;
239235

240236
// Now that we have the lock, we can actually create the session
241237
// directory
242-
if create_dir(sess, &session_dir, "session").is_err() {
243-
return;
244-
}
238+
create_dir(sess, &session_dir, "session")?;
245239

246240
// Find a suitable source directory to copy from. Ignore those that we
247241
// have already tried before.
@@ -257,7 +251,7 @@ pub fn prepare_session_directory(
257251
);
258252

259253
sess.init_incr_comp_session(session_dir, directory_lock, false);
260-
return;
254+
return Ok(());
261255
};
262256

263257
debug!("attempting to copy data from source: {}", source_directory.display());
@@ -278,7 +272,7 @@ pub fn prepare_session_directory(
278272
}
279273

280274
sess.init_incr_comp_session(session_dir, directory_lock, true);
281-
return;
275+
return Ok(());
282276
} else {
283277
debug!("copying failed - trying next directory");
284278

@@ -478,7 +472,7 @@ fn generate_session_dir_path(crate_dir: &Path) -> PathBuf {
478472
directory_path
479473
}
480474

481-
fn create_dir(sess: &Session, path: &Path, dir_tag: &str) -> Result<(), ()> {
475+
fn create_dir(sess: &Session, path: &Path, dir_tag: &str) -> Result<(), ErrorReported> {
482476
match std_fs::create_dir_all(path) {
483477
Ok(()) => {
484478
debug!("{} directory created successfully", dir_tag);
@@ -492,13 +486,16 @@ fn create_dir(sess: &Session, path: &Path, dir_tag: &str) -> Result<(), ()> {
492486
path.display(),
493487
err
494488
));
495-
Err(())
489+
Err(ErrorReported)
496490
}
497491
}
498492
}
499493

500494
/// Allocate the lock-file and lock it.
501-
fn lock_directory(sess: &Session, session_dir: &Path) -> Result<(flock::Lock, PathBuf), ()> {
495+
fn lock_directory(
496+
sess: &Session,
497+
session_dir: &Path,
498+
) -> Result<(flock::Lock, PathBuf), ErrorReported> {
502499
let lock_file_path = lock_file_path(session_dir);
503500
debug!("lock_directory() - lock_file: {}", lock_file_path.display());
504501

@@ -510,13 +507,23 @@ fn lock_directory(sess: &Session, session_dir: &Path) -> Result<(flock::Lock, Pa
510507
) {
511508
// the lock should be exclusive
512509
Ok(lock) => Ok((lock, lock_file_path)),
513-
Err(err) => {
514-
sess.err(&format!(
510+
Err(lock_err) => {
511+
let mut err = sess.struct_err(&format!(
515512
"incremental compilation: could not create \
516-
session directory lock file: {}",
517-
err
513+
session directory lock file: {}",
514+
lock_err
518515
));
519-
Err(())
516+
if flock::Lock::error_unsupported(&lock_err) {
517+
err.note(&format!(
518+
"the filesystem for the incremental path at {} \
519+
does not appear to support locking, consider changing the \
520+
incremental path to a filesystem that supports locking \
521+
or disable incremental compilation",
522+
session_dir.display()
523+
));
524+
}
525+
err.emit();
526+
Err(ErrorReported)
520527
}
521528
}
522529
}

compiler/rustc_interface/src/passes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ pub fn register_plugins<'a>(
172172

173173
let disambiguator = util::compute_crate_disambiguator(sess);
174174
sess.crate_disambiguator.set(disambiguator).expect("not yet initialized");
175-
rustc_incremental::prepare_session_directory(sess, &crate_name, disambiguator);
175+
rustc_incremental::prepare_session_directory(sess, &crate_name, disambiguator)?;
176176

177177
if sess.opts.incremental.is_some() {
178178
sess.time("incr_comp_garbage_collect_session_directories", || {

compiler/rustc_interface/src/queries.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ impl<'tcx> Queries<'tcx> {
148148
self.compiler.register_lints.as_deref().unwrap_or_else(|| empty),
149149
krate,
150150
&crate_name,
151-
);
151+
)?;
152152

153153
// Compute the dependency graph (in the background). We want to do
154154
// this as early as possible, to give the DepGraph maximum time to
@@ -157,7 +157,7 @@ impl<'tcx> Queries<'tcx> {
157157
// called, which happens within passes::register_plugins().
158158
self.dep_graph_future().ok();
159159

160-
result
160+
Ok(result)
161161
})
162162
}
163163

0 commit comments

Comments
 (0)