Skip to content

Conversation

@RalfJung
Copy link
Member

A while ago, I added the big implicit RefCell for all file descriptions since it avoided interior mutability in eventfd. However, this requires us to hold the RefCell "lock" around the entire invocation of the read/write methods on an FD, which is not great. For instance, if an FD wants to update epoll notifications from inside its read/write, it is very crucial that the notification check does not end up accessing the FD itself. Such cycles, however, occur naturally:

  • eventfd wants to update notifications for itself
  • socketfd wants to update notifications on its "peer", which will in turn check its peer to see whether that buffer is empty -- and my peer's peer is myself.

This then also lets us simplify socketpair, which currently holds a weak reference to its peer and a weak reference to the peer's buffer -- that was previously needed precisely to avoid this issue.

}

// Check if the peer_fd closed
if self.peer_fd.upgrade().is_none() {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay looking at the old code here I think I have a theory for why behavior changed. But I can't imagine that the old behavior was intentional.

In think previously we had a situation where writebuf still existed but the peer was already destroyed. That's because a file descriptor reference gets invalidated before the call to FileDescriptor::close, but the Rc inside of it (in this case, for the buffer) survive until they get dropped, which happens at the end of FileDescriptor::close.

@oli-obk
Copy link
Contributor

oli-obk commented Aug 16, 2024

bors r plus

@bors
Copy link
Contributor

bors commented Aug 16, 2024

📌 Commit 01f5ae1 has been approved by oli-obk

It is now in the queue for this repository.

bors added a commit that referenced this pull request Aug 16, 2024
FD: remove big surrounding RefCell, simplify socketpair

A while ago, I added the big implicit RefCell for all file descriptions since it avoided interior mutability in `eventfd`. However, this requires us to hold the RefCell "lock" around the entire invocation of the `read`/`write` methods on an FD, which is not great. For instance, if an FD wants to update epoll notifications from inside its `read`/`write`, it is very crucial that the notification check does not end up accessing the FD itself. Such cycles, however, occur naturally:
- eventfd wants to update notifications for itself
- socketfd wants to update notifications on its "peer", which will in turn check *its* peer to see whether that buffer is empty -- and my peer's peer is myself.

This then also lets us simplify socketpair, which currently holds a weak reference to its peer *and* a weak reference to the peer's buffer -- that was previously needed precisely to avoid this issue.
@bors
Copy link
Contributor

bors commented Aug 16, 2024

⌛ Testing commit 01f5ae1 with merge a8ea598...

@RalfJung
Copy link
Member Author

Sorry, I tweaked the comment a bit more.^^

@bors r=oli-obk

@bors
Copy link
Contributor

bors commented Aug 16, 2024

📌 Commit b00d220 has been approved by oli-obk

It is now in the queue for this repository.

@bors
Copy link
Contributor

bors commented Aug 16, 2024

⌛ Testing commit b00d220 with merge 7888056...

@bors
Copy link
Contributor

bors commented Aug 16, 2024

☀️ Test successful - checks-actions
Approved by: oli-obk
Pushing 7888056 to master...

@bors bors merged commit 7888056 into rust-lang:master Aug 16, 2024
@bors bors mentioned this pull request Aug 16, 2024
@RalfJung RalfJung deleted the fd-refcell branch August 16, 2024 20:34
// Write to fd[0].
let data = "abcde".as_bytes().as_ptr();
res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5).try_into().unwrap() };
let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) };
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tiif btw, the test becomes a lot more readable if you avoid let mut res and all the try_into().unwrap(). Just use a new fresh res variable each time. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants