@@ -12,17 +12,15 @@ use crate::shims::unix::UnixFileDescription;
1212use crate :: * ;
1313
1414/// An `Epoll` file descriptor connects file handles and epoll events
15- #[ derive( Clone , Debug , Default ) ]
15+ #[ derive( Debug , Default ) ]
1616struct Epoll {
1717 /// A map of EpollEventInterests registered under this epoll instance.
1818 /// Each entry is differentiated using FdId and file descriptor value.
1919 interest_list : RefCell < BTreeMap < ( FdId , i32 ) , Rc < RefCell < EpollEventInterest > > > > ,
2020 /// A map of EpollEventInstance that will be returned when `epoll_wait` is called.
2121 /// Similar to interest_list, the entry is also differentiated using FdId
2222 /// and file descriptor value.
23- // This is an Rc because EpollInterest need to hold a reference to update
24- // it.
25- ready_list : Rc < ReadyList > ,
23+ ready_list : ReadyList ,
2624 /// A list of thread ids blocked on this epoll instance.
2725 blocked_tid : RefCell < Vec < ThreadId > > ,
2826}
@@ -59,7 +57,7 @@ impl EpollEventInstance {
5957/// see the man page:
6058///
6159/// <https://man7.org/linux/man-pages/man2/epoll_ctl.2.html>
62- #[ derive( Clone , Debug ) ]
60+ #[ derive( Debug ) ]
6361pub struct EpollEventInterest {
6462 /// The file descriptor value of the file description registered.
6563 /// This is only used for ready_list, to inform userspace which FD triggered an event.
@@ -73,9 +71,9 @@ pub struct EpollEventInterest {
7371 /// but only u64 is supported for now.
7472 /// <https://man7.org/linux/man-pages/man3/epoll_event.3type.html>
7573 data : u64 ,
76- /// Ready list of the epoll instance under which this EpollEventInterest is registered.
77- ready_list : Rc < ReadyList > ,
7874 /// The epoll file description that this EpollEventInterest is registered under.
75+ /// This is weak to avoid cycles, but an upgrade is always guaranteed to succeed
76+ /// because only the `Epoll` holds a strong ref to a `EpollEventInterest`.
7977 weak_epfd : WeakFileDescriptionRef < Epoll > ,
8078}
8179
@@ -273,12 +271,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
273271 let Some ( epfd) = this. machine . fds . get ( epfd_value) else {
274272 return this. set_last_error_and_return_i32 ( LibcError ( "EBADF" ) ) ;
275273 } ;
276- let epoll_file_description = epfd
274+ let epfd = epfd
277275 . downcast :: < Epoll > ( )
278276 . ok_or_else ( || err_unsup_format ! ( "non-epoll FD passed to `epoll_ctl`" ) ) ?;
279277
280- let mut interest_list = epoll_file_description. interest_list . borrow_mut ( ) ;
281- let ready_list = & epoll_file_description. ready_list ;
278+ let mut interest_list = epfd. interest_list . borrow_mut ( ) ;
282279
283280 let Some ( fd_ref) = this. machine . fds . get ( fd) else {
284281 return this. set_last_error_and_return_i32 ( LibcError ( "EBADF" ) ) ;
@@ -345,8 +342,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
345342 fd_num : fd,
346343 events,
347344 data,
348- ready_list : Rc :: clone ( ready_list) ,
349- weak_epfd : FileDescriptionRef :: downgrade ( & epoll_file_description) ,
345+ weak_epfd : FileDescriptionRef :: downgrade ( & epfd) ,
350346 } ) ) ;
351347 // Notification will be returned for current epfd if there is event in the file
352348 // descriptor we registered.
@@ -379,7 +375,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
379375 drop ( epoll_interest) ;
380376
381377 // Remove related epoll_interest from ready list.
382- ready_list. mapping . borrow_mut ( ) . remove ( & epoll_key) ;
378+ epfd . ready_list . mapping . borrow_mut ( ) . remove ( & epoll_key) ;
383379
384380 // Remove dangling EpollEventInterest from its global table.
385381 // .unwrap() below should succeed because the file description id must have registered
@@ -592,14 +588,15 @@ fn check_and_update_one_event_interest<'tcx>(
592588 // Get the bitmask of ready events for a file description.
593589 let ready_events_bitmask = fd_ref. as_unix ( ) . get_epoll_ready_events ( ) ?. get_event_bitmask ( ecx) ;
594590 let epoll_event_interest = interest. borrow ( ) ;
591+ let epfd = epoll_event_interest. weak_epfd . upgrade ( ) . unwrap ( ) ;
595592 // This checks if any of the events specified in epoll_event_interest.events
596593 // match those in ready_events.
597594 let flags = epoll_event_interest. events & ready_events_bitmask;
598595 // If there is any event that we are interested in being specified as ready,
599596 // insert an epoll_return to the ready list.
600597 if flags != 0 {
601598 let epoll_key = ( id, epoll_event_interest. fd_num ) ;
602- let ready_list = & mut epoll_event_interest . ready_list . mapping . borrow_mut ( ) ;
599+ let mut ready_list = epfd . ready_list . mapping . borrow_mut ( ) ;
603600 let mut event_instance = EpollEventInstance :: new ( flags, epoll_event_interest. data ) ;
604601 // If we are tracking data races, remember the current clock so we can sync with it later.
605602 ecx. release_clock ( |clock| {
0 commit comments