mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Do not generate extraneous IN_CLOSE inotify events.
IN_CLOSE should only be generated when a file description loses its last reference; not when a file descriptor is closed. See fs/file_table.c:__fput. Updates #5348. PiperOrigin-RevId: 353810697
This commit is contained in:
@@ -159,13 +159,6 @@ func (f *FDTable) dropVFS2(ctx context.Context, file *vfs.FileDescription) {
|
||||
panic(fmt.Sprintf("UnlockPOSIX failed: %v", err))
|
||||
}
|
||||
|
||||
// Generate inotify events.
|
||||
ev := uint32(linux.IN_CLOSE_NOWRITE)
|
||||
if file.IsWritable() {
|
||||
ev = linux.IN_CLOSE_WRITE
|
||||
}
|
||||
file.Dentry().InotifyWithParent(ctx, ev, 0, vfs.PathEvent)
|
||||
|
||||
// Drop the table's reference.
|
||||
file.DecRef(ctx)
|
||||
}
|
||||
|
||||
@@ -161,6 +161,13 @@ func (fd *FileDescription) Init(impl FileDescriptionImpl, flags uint32, mnt *Mou
|
||||
// DecRef decrements fd's reference count.
|
||||
func (fd *FileDescription) DecRef(ctx context.Context) {
|
||||
fd.FileDescriptionRefs.DecRef(func() {
|
||||
// Generate inotify events.
|
||||
ev := uint32(linux.IN_CLOSE_NOWRITE)
|
||||
if fd.IsWritable() {
|
||||
ev = linux.IN_CLOSE_WRITE
|
||||
}
|
||||
fd.Dentry().InotifyWithParent(ctx, ev, 0, PathEvent)
|
||||
|
||||
// Unregister fd from all epoll instances.
|
||||
fd.epollMu.Lock()
|
||||
epolls := fd.epolls
|
||||
|
||||
@@ -782,6 +782,38 @@ TEST(Inotify, MoveWatchedTargetGeneratesEvents) {
|
||||
EXPECT_EQ(events[0].cookie, events[1].cookie);
|
||||
}
|
||||
|
||||
// Tests that close events are only emitted when a file description drops its
|
||||
// last reference.
|
||||
TEST(Inotify, DupFD) {
|
||||
SKIP_IF(IsRunningWithVFS1());
|
||||
|
||||
const TempPath file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
|
||||
const FileDescriptor inotify_fd =
|
||||
ASSERT_NO_ERRNO_AND_VALUE(InotifyInit1(IN_NONBLOCK));
|
||||
|
||||
const int wd = ASSERT_NO_ERRNO_AND_VALUE(
|
||||
InotifyAddWatch(inotify_fd.get(), file.path(), IN_ALL_EVENTS));
|
||||
|
||||
FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDONLY));
|
||||
FileDescriptor fd2 = ASSERT_NO_ERRNO_AND_VALUE(fd.Dup());
|
||||
|
||||
std::vector<Event> events =
|
||||
ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
|
||||
EXPECT_THAT(events, Are({
|
||||
Event(IN_OPEN, wd),
|
||||
}));
|
||||
|
||||
fd.reset();
|
||||
events = ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
|
||||
EXPECT_THAT(events, Are({}));
|
||||
|
||||
fd2.reset();
|
||||
events = ASSERT_NO_ERRNO_AND_VALUE(DrainEvents(inotify_fd.get()));
|
||||
EXPECT_THAT(events, Are({
|
||||
Event(IN_CLOSE_NOWRITE, wd),
|
||||
}));
|
||||
}
|
||||
|
||||
TEST(Inotify, CoalesceEvents) {
|
||||
const TempPath root = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
|
||||
const FileDescriptor fd =
|
||||
|
||||
Reference in New Issue
Block a user