mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-05-19 01:30:21 -07:00
worker: better error handling for memory maps
Previously, we would bail out of using memory maps if we could detect ahead of time that opening a memory map would fail. The only case we checked was whether the file size was 0 or not. This is actually insufficient. The mmap call can return ENODEV errors when a file doesn't support memory maps. This is the case for new files exposed by Linux, for example, /sys/devices/system/cpu/vulnerabilities/meltdown. We fix this by checking the actual error codes returned by the mmap call. If ENODEV (or EOVERFLOW) is returned, then we fall back to regular `read` calls. If any other error occurs, we report it to the user. Fixes #760
This commit is contained in:
parent
0fedaa7d28
commit
93943793c3
@ -9,6 +9,7 @@ extern crate grep;
|
||||
extern crate ignore;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate libc;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate memchr;
|
||||
@ -339,7 +340,6 @@ fn eprint_nothing_searched() {
|
||||
// https://github.com/BurntSushi/ripgrep/issues/200.
|
||||
#[cfg(unix)]
|
||||
fn reset_sigpipe() {
|
||||
extern crate libc;
|
||||
unsafe {
|
||||
libc::signal(libc::SIGPIPE, libc::SIG_DFL);
|
||||
}
|
||||
|
@ -310,7 +310,10 @@ impl Worker {
|
||||
// regular read calls.
|
||||
return self.search(printer, path, file);
|
||||
}
|
||||
let mmap = unsafe { Mmap::map(file)? };
|
||||
let mmap = match self.mmap(file)? {
|
||||
None => return self.search(printer, path, file),
|
||||
Some(mmap) => mmap,
|
||||
};
|
||||
let buf = &*mmap;
|
||||
if buf.len() >= 3 && Encoding::for_bom(buf).is_some() {
|
||||
// If we have a UTF-16 bom in our memory map, then we need to fall
|
||||
@ -330,4 +333,28 @@ impl Worker {
|
||||
.text(self.opts.text)
|
||||
.run())
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn mmap(&self, file: &File) -> Result<Option<Mmap>> {
|
||||
Ok(Some(mmap_readonly(file)?))
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn mmap(&self, file: &File) -> Result<Option<Mmap>> {
|
||||
use libc::{ENODEV, EOVERFLOW};
|
||||
|
||||
let err = match mmap_readonly(file) {
|
||||
Ok(mmap) => return Ok(Some(mmap)),
|
||||
Err(err) => err,
|
||||
};
|
||||
let code = err.raw_os_error();
|
||||
if code == Some(ENODEV) || code == Some(EOVERFLOW) {
|
||||
return Ok(None);
|
||||
}
|
||||
Err(From::from(err))
|
||||
}
|
||||
}
|
||||
|
||||
fn mmap_readonly(file: &File) -> io::Result<Mmap> {
|
||||
unsafe { Mmap::map(file) }
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user