diff --git a/pkg/sentry/vfs/file_description.go b/pkg/sentry/vfs/file_description.go index d54f97f00..d76d09545 100644 --- a/pkg/sentry/vfs/file_description.go +++ b/pkg/sentry/vfs/file_description.go @@ -276,6 +276,7 @@ func (fd *FileDescription) SetStatusFlags(ctx context.Context, creds *auth.Crede // TODO(gvisor.dev/issue/1035): FileDescriptionImpl.SetOAsync()? const settableFlags = linux.O_APPEND | linux.O_ASYNC | linux.O_DIRECT | linux.O_NOATIME | linux.O_NONBLOCK fd.flagsMu.Lock() + defer fd.flagsMu.Unlock() if fd.asyncHandler != nil { // Use fd.statusFlags instead of oldFlags, which may have become outdated, // to avoid double registering/unregistering. @@ -288,7 +289,6 @@ func (fd *FileDescription) SetStatusFlags(ctx context.Context, creds *auth.Crede } } fd.statusFlags.Store((oldFlags &^ settableFlags) | (flags & settableFlags)) - fd.flagsMu.Unlock() return nil } @@ -944,7 +944,7 @@ func (fd *FileDescription) SetAsyncHandler(newHandler func() FileAsync) (FileAsy if fd.asyncHandler == nil { fd.asyncHandler = newHandler() if fd.statusFlags.RacyLoad()&linux.O_ASYNC != 0 { - if err := fd.asyncHandler.Register(fd); err != nil { + if err := fd.impl.RegisterFileAsyncHandler(fd); err != nil { return nil, err } } diff --git a/test/syscalls/linux/fcntl.cc b/test/syscalls/linux/fcntl.cc index 94696409e..db5edfed3 100644 --- a/test/syscalls/linux/fcntl.cc +++ b/test/syscalls/linux/fcntl.cc @@ -1510,6 +1510,25 @@ TEST_F(FcntlSignalTest, SignalFD) { syscall(SYS_tkill, tid, SIGIO); } +TEST_F(FcntlSignalTest, SignalFDSetSigAfterASYNC) { + // Create the signalfd. + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGIO); + FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(NewSignalFD(&mask, 0)); + + const auto signal_cleanup = + ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGIO)); + ASSERT_THAT(fcntl(fd.get(), F_SETOWN, getpid()), SyscallSucceeds()); + int old_flags; + ASSERT_THAT(old_flags = fcntl(fd.get(), F_GETFL), SyscallSucceeds()); + ASSERT_THAT(fcntl(fd.get(), F_SETFL, old_flags | O_ASYNC), SyscallSucceeds()); + ASSERT_THAT(fcntl(fd.get(), F_SETSIG, 0), SyscallSucceeds()); + + int tid = syscall(SYS_gettid); + syscall(SYS_tkill, tid, SIGIO); +} + TEST_F(FcntlSignalTest, SetSigCustom) { const auto signal_cleanup = ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGUSR1));