mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 00:47:36 +00:00
Kernel: Report POLLNVAL events in sys$poll instead of returning EBADF
As required by Dr. Posix.
This commit is contained in:
parent
e32f6903f6
commit
275e5cdb64
3 changed files with 22 additions and 5 deletions
|
@ -50,7 +50,10 @@ ErrorOr<FlatPtr> Process::sys$poll(Userspace<Syscall::SC_poll_params const*> use
|
||||||
TRY(m_fds.with_shared([&](auto& fds) -> ErrorOr<void> {
|
TRY(m_fds.with_shared([&](auto& fds) -> ErrorOr<void> {
|
||||||
for (size_t i = 0; i < params.nfds; i++) {
|
for (size_t i = 0; i < params.nfds; i++) {
|
||||||
auto& pfd = fds_copy[i];
|
auto& pfd = fds_copy[i];
|
||||||
auto description = TRY(fds.open_file_description(pfd.fd));
|
RefPtr<OpenFileDescription> description;
|
||||||
|
auto description_or_error = fds.open_file_description(pfd.fd);
|
||||||
|
if (!description_or_error.is_error())
|
||||||
|
description = description_or_error.release_value();
|
||||||
BlockFlags block_flags = BlockFlags::WriteError | BlockFlags::WriteHangUp; // always want POLLERR, POLLHUP, POLLNVAL
|
BlockFlags block_flags = BlockFlags::WriteError | BlockFlags::WriteHangUp; // always want POLLERR, POLLHUP, POLLNVAL
|
||||||
if (pfd.events & POLLIN)
|
if (pfd.events & POLLIN)
|
||||||
block_flags |= BlockFlags::Read;
|
block_flags |= BlockFlags::Read;
|
||||||
|
@ -93,11 +96,13 @@ ErrorOr<FlatPtr> Process::sys$poll(Userspace<Syscall::SC_poll_params const*> use
|
||||||
if (fds_entry.unblocked_flags == BlockFlags::None)
|
if (fds_entry.unblocked_flags == BlockFlags::None)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (has_any_flag(fds_entry.unblocked_flags, BlockFlags::WriteError | BlockFlags::WriteHangUp)) {
|
if (has_any_flag(fds_entry.unblocked_flags, BlockFlags::WriteError | BlockFlags::WriteHangUp) || !fds_entry.description) {
|
||||||
if (has_flag(fds_entry.unblocked_flags, BlockFlags::WriteError))
|
if (has_flag(fds_entry.unblocked_flags, BlockFlags::WriteError))
|
||||||
pfd.revents |= POLLERR;
|
pfd.revents |= POLLERR;
|
||||||
if (has_flag(fds_entry.unblocked_flags, BlockFlags::WriteHangUp))
|
if (has_flag(fds_entry.unblocked_flags, BlockFlags::WriteHangUp))
|
||||||
pfd.revents |= POLLHUP;
|
pfd.revents |= POLLHUP;
|
||||||
|
if (!fds_entry.description)
|
||||||
|
pfd.revents |= POLLNVAL;
|
||||||
} else {
|
} else {
|
||||||
if (has_flag(fds_entry.unblocked_flags, BlockFlags::Read)) {
|
if (has_flag(fds_entry.unblocked_flags, BlockFlags::Read)) {
|
||||||
VERIFY(pfd.events & POLLIN);
|
VERIFY(pfd.events & POLLIN);
|
||||||
|
|
|
@ -668,7 +668,7 @@ public:
|
||||||
class SelectBlocker final : public FileBlocker {
|
class SelectBlocker final : public FileBlocker {
|
||||||
public:
|
public:
|
||||||
struct FDInfo {
|
struct FDInfo {
|
||||||
NonnullRefPtr<OpenFileDescription> description;
|
RefPtr<OpenFileDescription> description;
|
||||||
BlockFlags block_flags { BlockFlags::None };
|
BlockFlags block_flags { BlockFlags::None };
|
||||||
BlockFlags unblocked_flags { BlockFlags::None };
|
BlockFlags unblocked_flags { BlockFlags::None };
|
||||||
};
|
};
|
||||||
|
|
|
@ -360,6 +360,10 @@ bool Thread::SelectBlocker::setup_blocker()
|
||||||
|
|
||||||
if (!should_block)
|
if (!should_block)
|
||||||
continue;
|
continue;
|
||||||
|
if (!fd_entry.description) {
|
||||||
|
should_block = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!fd_entry.description->blocker_set().add_blocker(*this, &fd_entry))
|
if (!fd_entry.description->blocker_set().add_blocker(*this, &fd_entry))
|
||||||
should_block = false;
|
should_block = false;
|
||||||
}
|
}
|
||||||
|
@ -371,8 +375,10 @@ Thread::SelectBlocker::~SelectBlocker() = default;
|
||||||
void Thread::SelectBlocker::finalize()
|
void Thread::SelectBlocker::finalize()
|
||||||
{
|
{
|
||||||
Thread::FileBlocker::finalize();
|
Thread::FileBlocker::finalize();
|
||||||
for (auto& fd_entry : m_fds)
|
for (auto& fd_entry : m_fds) {
|
||||||
fd_entry.description->blocker_set().remove_blocker(*this);
|
if (fd_entry.description)
|
||||||
|
fd_entry.description->blocker_set().remove_blocker(*this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Thread::SelectBlocker::will_unblock_immediately_without_blocking(UnblockImmediatelyReason reason)
|
void Thread::SelectBlocker::will_unblock_immediately_without_blocking(UnblockImmediatelyReason reason)
|
||||||
|
@ -397,6 +403,7 @@ bool Thread::SelectBlocker::unblock_if_conditions_are_met(bool from_add_blocker,
|
||||||
if (m_did_unblock)
|
if (m_did_unblock)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
VERIFY(fd_info.description);
|
||||||
auto unblock_flags = fd_info.description->should_unblock(fd_info.block_flags);
|
auto unblock_flags = fd_info.description->should_unblock(fd_info.block_flags);
|
||||||
if (unblock_flags == BlockFlags::None)
|
if (unblock_flags == BlockFlags::None)
|
||||||
return false;
|
return false;
|
||||||
|
@ -421,6 +428,11 @@ size_t Thread::SelectBlocker::collect_unblocked_flags()
|
||||||
for (auto& fd_entry : m_fds) {
|
for (auto& fd_entry : m_fds) {
|
||||||
VERIFY(fd_entry.block_flags != FileBlocker::BlockFlags::None);
|
VERIFY(fd_entry.block_flags != FileBlocker::BlockFlags::None);
|
||||||
|
|
||||||
|
if (!fd_entry.description) {
|
||||||
|
count++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// unblock will have set at least the first descriptor's unblock
|
// unblock will have set at least the first descriptor's unblock
|
||||||
// flags that triggered the unblock. Make sure we don't discard that
|
// flags that triggered the unblock. Make sure we don't discard that
|
||||||
// information as it may have changed by now!
|
// information as it may have changed by now!
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue