mirror of
https://github.com/oxalica/nil.git
synced 2025-12-23 09:19:49 +00:00
Fix stuck on non-regular files and report loading errors
This commit is contained in:
parent
5700b00872
commit
f2b2647975
3 changed files with 53 additions and 18 deletions
14
Cargo.lock
generated
14
Cargo.lock
generated
|
|
@ -388,15 +388,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.141"
|
||||
version = "0.2.142"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
|
||||
checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.3.1"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
|
||||
checksum = "b64f40e5e03e0d54f03845c8197d0291253cdbedfb1cb46b13c2c117554a9f4c"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
|
|
@ -476,10 +476,10 @@ dependencies = [
|
|||
"atty",
|
||||
"codespan-reporting",
|
||||
"ide",
|
||||
"libc",
|
||||
"log",
|
||||
"lsp-types",
|
||||
"nix-interop",
|
||||
"rustix",
|
||||
"serde_json",
|
||||
"slab",
|
||||
"syntax",
|
||||
|
|
@ -710,9 +710,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
|||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.37.11"
|
||||
version = "0.37.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77"
|
||||
checksum = "bc809f704c03a812ac71f22456c857be34185cac691a4316f27ab0f633bb9009"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
|
|
|
|||
|
|
@ -34,5 +34,5 @@ features = [
|
|||
"tracing-log",
|
||||
]
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
libc = "0.2.137"
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
rustix = { version = "0.37.17", default-features = false, features = ["fs"] }
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ use std::borrow::BorrowMut;
|
|||
use std::cell::Cell;
|
||||
use std::collections::HashMap;
|
||||
use std::future::{ready, Future};
|
||||
use std::io::{ErrorKind, Read};
|
||||
use std::ops::ControlFlow;
|
||||
use std::panic::UnwindSafe;
|
||||
use std::path::Path;
|
||||
|
|
@ -352,23 +353,57 @@ impl Server {
|
|||
tracing::debug!("Watched files changed: {params:?}");
|
||||
|
||||
let mut flake_files_changed = true;
|
||||
for FileEvent { uri, typ } in ¶ms.changes {
|
||||
for &FileEvent { ref uri, mut typ } in ¶ms.changes {
|
||||
// Don't reload files maintained by the client.
|
||||
if self.opened_files.contains_key(uri) {
|
||||
continue;
|
||||
}
|
||||
let Ok(path) = uri.to_file_path() else { continue };
|
||||
match *typ {
|
||||
FileChangeType::CREATED | FileChangeType::CHANGED => {
|
||||
if let Ok(text) = std::fs::read_to_string(&path) {
|
||||
self.set_vfs_file_content(uri, text);
|
||||
|
||||
if matches!(typ, FileChangeType::CREATED | FileChangeType::CHANGED) {
|
||||
match (|| -> std::io::Result<_> {
|
||||
#[cfg(unix)]
|
||||
use rustix::fs::{fcntl_getfl, fcntl_setfl, OFlags, OpenOptionsExt};
|
||||
|
||||
// Rule out non-regular files which may block `open()` infinitely
|
||||
// (eg. FIFO). We open it with `O_NONBLOCK` and check it before reading.
|
||||
let mut options = std::fs::File::options();
|
||||
options.read(true);
|
||||
#[cfg(unix)]
|
||||
options.custom_flags(OFlags::NONBLOCK.bits() as _);
|
||||
|
||||
let mut file = options.open(&path)?;
|
||||
let ft = file.metadata()?.file_type();
|
||||
if !ft.is_file() {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("non-regular file type: {ft:?}"),
|
||||
));
|
||||
}
|
||||
|
||||
// Remove the O_NONBLOCK flag for blocking read.
|
||||
#[cfg(unix)]
|
||||
{
|
||||
let flags = fcntl_getfl(&file)? - OFlags::NONBLOCK;
|
||||
fcntl_setfl(&file, flags)?;
|
||||
}
|
||||
|
||||
let mut buf = String::new();
|
||||
file.read_to_string(&mut buf)?;
|
||||
Ok(buf)
|
||||
})() {
|
||||
Ok(text) => self.set_vfs_file_content(uri, text),
|
||||
Err(err) if matches!(err.kind(), ErrorKind::NotFound) => {
|
||||
// File gets removed at the time calling `open()`.
|
||||
typ = FileChangeType::DELETED;
|
||||
}
|
||||
Err(err) => tracing::error!("Ignore file {path:?}: {err}"),
|
||||
}
|
||||
FileChangeType::DELETED => {
|
||||
let _: Result<_> = self.vfs.write().unwrap().remove_uri(uri);
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
if typ == FileChangeType::DELETED {
|
||||
let _: Result<_> = self.vfs.write().unwrap().remove_uri(uri);
|
||||
}
|
||||
|
||||
if let Ok(relative) = path.strip_prefix(&self.config.root_path) {
|
||||
if relative == Path::new(FLAKE_FILE) || relative == Path::new(FLAKE_LOCK_FILE) {
|
||||
flake_files_changed = true;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue