Skip to content

Commit 17cfbc6

Browse files
committed
FD: remove big surrounding RefCell, simplify socketpair
1 parent 86783be commit 17cfbc6

File tree

6 files changed

+169
-187
lines changed

6 files changed

+169
-187
lines changed

src/tools/miri/src/shims/unix/fd.rs

Lines changed: 46 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
//! standard file descriptors (stdin/stdout/stderr).
33
44
use std::any::Any;
5-
use std::cell::{Ref, RefCell, RefMut};
65
use std::collections::BTreeMap;
76
use std::io::{self, ErrorKind, IsTerminal, Read, SeekFrom, Write};
7+
use std::ops::Deref;
88
use std::rc::Rc;
99
use std::rc::Weak;
1010

@@ -27,7 +27,7 @@ pub trait FileDescription: std::fmt::Debug + Any {
2727

2828
/// Reads as much as possible into the given buffer, and returns the number of bytes read.
2929
fn read<'tcx>(
30-
&mut self,
30+
&self,
3131
_communicate_allowed: bool,
3232
_fd_id: FdId,
3333
_bytes: &mut [u8],
@@ -38,7 +38,7 @@ pub trait FileDescription: std::fmt::Debug + Any {
3838

3939
/// Writes as much as possible from the given buffer, and returns the number of bytes written.
4040
fn write<'tcx>(
41-
&mut self,
41+
&self,
4242
_communicate_allowed: bool,
4343
_fd_id: FdId,
4444
_bytes: &[u8],
@@ -50,7 +50,7 @@ pub trait FileDescription: std::fmt::Debug + Any {
5050
/// Reads as much as possible into the given buffer from a given offset,
5151
/// and returns the number of bytes read.
5252
fn pread<'tcx>(
53-
&mut self,
53+
&self,
5454
_communicate_allowed: bool,
5555
_bytes: &mut [u8],
5656
_offset: u64,
@@ -62,7 +62,7 @@ pub trait FileDescription: std::fmt::Debug + Any {
6262
/// Writes as much as possible from the given buffer starting at a given offset,
6363
/// and returns the number of bytes written.
6464
fn pwrite<'tcx>(
65-
&mut self,
65+
&self,
6666
_communicate_allowed: bool,
6767
_bytes: &[u8],
6868
_offset: u64,
@@ -74,7 +74,7 @@ pub trait FileDescription: std::fmt::Debug + Any {
7474
/// Seeks to the given offset (which can be relative to the beginning, end, or current position).
7575
/// Returns the new position from the start of the stream.
7676
fn seek<'tcx>(
77-
&mut self,
77+
&self,
7878
_communicate_allowed: bool,
7979
_offset: SeekFrom,
8080
) -> InterpResult<'tcx, io::Result<u64>> {
@@ -111,14 +111,9 @@ pub trait FileDescription: std::fmt::Debug + Any {
111111

112112
impl dyn FileDescription {
113113
#[inline(always)]
114-
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
114+
pub fn downcast<T: Any>(&self) -> Option<&T> {
115115
(self as &dyn Any).downcast_ref()
116116
}
117-
118-
#[inline(always)]
119-
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
120-
(self as &mut dyn Any).downcast_mut()
121-
}
122117
}
123118

124119
impl FileDescription for io::Stdin {
@@ -127,7 +122,7 @@ impl FileDescription for io::Stdin {
127122
}
128123

129124
fn read<'tcx>(
130-
&mut self,
125+
&self,
131126
communicate_allowed: bool,
132127
_fd_id: FdId,
133128
bytes: &mut [u8],
@@ -137,7 +132,7 @@ impl FileDescription for io::Stdin {
137132
// We want isolation mode to be deterministic, so we have to disallow all reads, even stdin.
138133
helpers::isolation_abort_error("`read` from stdin")?;
139134
}
140-
Ok(Read::read(self, bytes))
135+
Ok(Read::read(&mut { self }, bytes))
141136
}
142137

143138
fn is_tty(&self, communicate_allowed: bool) -> bool {
@@ -151,14 +146,14 @@ impl FileDescription for io::Stdout {
151146
}
152147

153148
fn write<'tcx>(
154-
&mut self,
149+
&self,
155150
_communicate_allowed: bool,
156151
_fd_id: FdId,
157152
bytes: &[u8],
158153
_ecx: &mut MiriInterpCx<'tcx>,
159154
) -> InterpResult<'tcx, io::Result<usize>> {
160155
// We allow writing to stderr even with isolation enabled.
161-
let result = Write::write(self, bytes);
156+
let result = Write::write(&mut { self }, bytes);
162157
// Stdout is buffered, flush to make sure it appears on the
163158
// screen. This is the write() syscall of the interpreted
164159
// program, we want it to correspond to a write() syscall on
@@ -180,7 +175,7 @@ impl FileDescription for io::Stderr {
180175
}
181176

182177
fn write<'tcx>(
183-
&mut self,
178+
&self,
184179
_communicate_allowed: bool,
185180
_fd_id: FdId,
186181
bytes: &[u8],
@@ -206,7 +201,7 @@ impl FileDescription for NullOutput {
206201
}
207202

208203
fn write<'tcx>(
209-
&mut self,
204+
&self,
210205
_communicate_allowed: bool,
211206
_fd_id: FdId,
212207
bytes: &[u8],
@@ -221,26 +216,23 @@ impl FileDescription for NullOutput {
221216
#[derive(Clone, Debug)]
222217
pub struct FileDescWithId<T: FileDescription + ?Sized> {
223218
id: FdId,
224-
file_description: RefCell<Box<T>>,
219+
file_description: Box<T>,
225220
}
226221

227222
#[derive(Clone, Debug)]
228223
pub struct FileDescriptionRef(Rc<FileDescWithId<dyn FileDescription>>);
229224

230-
impl FileDescriptionRef {
231-
fn new(fd: impl FileDescription, id: FdId) -> Self {
232-
FileDescriptionRef(Rc::new(FileDescWithId {
233-
id,
234-
file_description: RefCell::new(Box::new(fd)),
235-
}))
236-
}
225+
impl Deref for FileDescriptionRef {
226+
type Target = dyn FileDescription;
237227

238-
pub fn borrow(&self) -> Ref<'_, dyn FileDescription> {
239-
Ref::map(self.0.file_description.borrow(), |fd| fd.as_ref())
228+
fn deref(&self) -> &Self::Target {
229+
&*self.0.file_description
240230
}
231+
}
241232

242-
pub fn borrow_mut(&self) -> RefMut<'_, dyn FileDescription> {
243-
RefMut::map(self.0.file_description.borrow_mut(), |fd| fd.as_mut())
233+
impl FileDescriptionRef {
234+
fn new(fd: impl FileDescription, id: FdId) -> Self {
235+
FileDescriptionRef(Rc::new(FileDescWithId { id, file_description: Box::new(fd) }))
244236
}
245237

246238
pub fn close<'tcx>(
@@ -256,7 +248,7 @@ impl FileDescriptionRef {
256248
// Remove entry from the global epoll_event_interest table.
257249
ecx.machine.epoll_interests.remove(id);
258250

259-
RefCell::into_inner(fd.file_description).close(communicate_allowed, ecx)
251+
fd.file_description.close(communicate_allowed, ecx)
260252
}
261253
None => Ok(Ok(())),
262254
}
@@ -277,7 +269,7 @@ impl FileDescriptionRef {
277269
ecx: &mut InterpCx<'tcx, MiriMachine<'tcx>>,
278270
) -> InterpResult<'tcx, ()> {
279271
use crate::shims::unix::linux::epoll::EvalContextExt;
280-
ecx.check_and_update_readiness(self.get_id(), || self.borrow_mut().get_epoll_ready_events())
272+
ecx.check_and_update_readiness(self.get_id(), || self.get_epoll_ready_events())
281273
}
282274
}
283275

@@ -334,11 +326,20 @@ impl FdTable {
334326
fds
335327
}
336328

337-
/// Insert a new file description to the FdTable.
338-
pub fn insert_new(&mut self, fd: impl FileDescription) -> i32 {
329+
pub fn new_ref(&mut self, fd: impl FileDescription) -> FileDescriptionRef {
339330
let file_handle = FileDescriptionRef::new(fd, self.next_file_description_id);
340331
self.next_file_description_id = FdId(self.next_file_description_id.0.strict_add(1));
341-
self.insert_ref_with_min_fd(file_handle, 0)
332+
file_handle
333+
}
334+
335+
/// Insert a new file description to the FdTable.
336+
pub fn insert_new(&mut self, fd: impl FileDescription) -> i32 {
337+
let fd_ref = self.new_ref(fd);
338+
self.insert(fd_ref)
339+
}
340+
341+
pub fn insert(&mut self, fd_ref: FileDescriptionRef) -> i32 {
342+
self.insert_ref_with_min_fd(fd_ref, 0)
342343
}
343344

344345
/// Insert a file description, giving it a file descriptor that is at least `min_fd`.
@@ -368,17 +369,7 @@ impl FdTable {
368369
new_fd
369370
}
370371

371-
pub fn get(&self, fd: i32) -> Option<Ref<'_, dyn FileDescription>> {
372-
let fd = self.fds.get(&fd)?;
373-
Some(fd.borrow())
374-
}
375-
376-
pub fn get_mut(&self, fd: i32) -> Option<RefMut<'_, dyn FileDescription>> {
377-
let fd = self.fds.get(&fd)?;
378-
Some(fd.borrow_mut())
379-
}
380-
381-
pub fn get_ref(&self, fd: i32) -> Option<FileDescriptionRef> {
372+
pub fn get(&self, fd: i32) -> Option<FileDescriptionRef> {
382373
let fd = self.fds.get(&fd)?;
383374
Some(fd.clone())
384375
}
@@ -397,7 +388,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
397388
fn dup(&mut self, old_fd: i32) -> InterpResult<'tcx, Scalar> {
398389
let this = self.eval_context_mut();
399390

400-
let Some(dup_fd) = this.machine.fds.get_ref(old_fd) else {
391+
let Some(dup_fd) = this.machine.fds.get(old_fd) else {
401392
return Ok(Scalar::from_i32(this.fd_not_found()?));
402393
};
403394
Ok(Scalar::from_i32(this.machine.fds.insert_ref_with_min_fd(dup_fd, 0)))
@@ -406,7 +397,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
406397
fn dup2(&mut self, old_fd: i32, new_fd: i32) -> InterpResult<'tcx, Scalar> {
407398
let this = self.eval_context_mut();
408399

409-
let Some(dup_fd) = this.machine.fds.get_ref(old_fd) else {
400+
let Some(dup_fd) = this.machine.fds.get(old_fd) else {
410401
return Ok(Scalar::from_i32(this.fd_not_found()?));
411402
};
412403
if new_fd != old_fd {
@@ -492,7 +483,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
492483
}
493484
let start = this.read_scalar(&args[2])?.to_i32()?;
494485

495-
match this.machine.fds.get_ref(fd) {
486+
match this.machine.fds.get(fd) {
496487
Some(dup_fd) =>
497488
Ok(Scalar::from_i32(this.machine.fds.insert_ref_with_min_fd(dup_fd, start))),
498489
None => Ok(Scalar::from_i32(this.fd_not_found()?)),
@@ -565,7 +556,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
565556
let communicate = this.machine.communicate();
566557

567558
// We temporarily dup the FD to be able to retain mutable access to `this`.
568-
let Some(fd) = this.machine.fds.get_ref(fd) else {
559+
let Some(fd) = this.machine.fds.get(fd) else {
569560
trace!("read: FD not found");
570561
return Ok(Scalar::from_target_isize(this.fd_not_found()?, this));
571562
};
@@ -576,14 +567,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
576567
// `usize::MAX` because it is bounded by the host's `isize`.
577568
let mut bytes = vec![0; usize::try_from(count).unwrap()];
578569
let result = match offset {
579-
None => fd.borrow_mut().read(communicate, fd.get_id(), &mut bytes, this),
570+
None => fd.read(communicate, fd.get_id(), &mut bytes, this),
580571
Some(offset) => {
581572
let Ok(offset) = u64::try_from(offset) else {
582573
let einval = this.eval_libc("EINVAL");
583574
this.set_last_error(einval)?;
584575
return Ok(Scalar::from_target_isize(-1, this));
585576
};
586-
fd.borrow_mut().pread(communicate, &mut bytes, offset, this)
577+
fd.pread(communicate, &mut bytes, offset, this)
587578
}
588579
};
589580

@@ -629,19 +620,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
629620

630621
let bytes = this.read_bytes_ptr_strip_provenance(buf, Size::from_bytes(count))?.to_owned();
631622
// We temporarily dup the FD to be able to retain mutable access to `this`.
632-
let Some(fd) = this.machine.fds.get_ref(fd) else {
623+
let Some(fd) = this.machine.fds.get(fd) else {
633624
return Ok(Scalar::from_target_isize(this.fd_not_found()?, this));
634625
};
635626

636627
let result = match offset {
637-
None => fd.borrow_mut().write(communicate, fd.get_id(), &bytes, this),
628+
None => fd.write(communicate, fd.get_id(), &bytes, this),
638629
Some(offset) => {
639630
let Ok(offset) = u64::try_from(offset) else {
640631
let einval = this.eval_libc("EINVAL");
641632
this.set_last_error(einval)?;
642633
return Ok(Scalar::from_target_isize(-1, this));
643634
};
644-
fd.borrow_mut().pwrite(communicate, &bytes, offset, this)
635+
fd.pwrite(communicate, &bytes, offset, this)
645636
}
646637
};
647638

0 commit comments

Comments
 (0)