Kernel: Cleanup and fix pipe
pipe now sends SIGPIPE and returns EPIPE when writing and no readers are open
This commit is contained in:
parent
37dea8aee7
commit
4d4fb3b6ec
|
@ -133,6 +133,9 @@ namespace Kernel
|
||||||
void del_epoll(class Epoll*);
|
void del_epoll(class Epoll*);
|
||||||
void epoll_notify(uint32_t event);
|
void epoll_notify(uint32_t event);
|
||||||
|
|
||||||
|
virtual void on_close(int status_flags) { (void)status_flags; }
|
||||||
|
virtual void on_clone(int status_flags) { (void)status_flags; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Directory API
|
// Directory API
|
||||||
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
|
|
|
@ -13,8 +13,9 @@ namespace Kernel
|
||||||
static BAN::ErrorOr<BAN::RefPtr<Inode>> create(const Credentials&);
|
static BAN::ErrorOr<BAN::RefPtr<Inode>> create(const Credentials&);
|
||||||
|
|
||||||
virtual bool is_pipe() const override { return true; }
|
virtual bool is_pipe() const override { return true; }
|
||||||
void clone_writing();
|
|
||||||
void close_writing();
|
void on_close(int status_flags) override;
|
||||||
|
void on_clone(int status_flags) override;
|
||||||
|
|
||||||
virtual ino_t ino() const override { return 0; } // FIXME
|
virtual ino_t ino() const override { return 0; } // FIXME
|
||||||
virtual Mode mode() const override { return { Mode::IFIFO | Mode::IRUSR | Mode::IWUSR }; }
|
virtual Mode mode() const override { return { Mode::IFIFO | Mode::IRUSR | Mode::IWUSR }; }
|
||||||
|
@ -39,7 +40,7 @@ namespace Kernel
|
||||||
|
|
||||||
virtual bool can_read_impl() const override { return m_buffer_size > 0; }
|
virtual bool can_read_impl() const override { return m_buffer_size > 0; }
|
||||||
virtual bool can_write_impl() const override { return true; }
|
virtual bool can_write_impl() const override { return true; }
|
||||||
virtual bool has_error_impl() const override { return false; }
|
virtual bool has_error_impl() const override { return m_reading_count == 0; }
|
||||||
virtual bool has_hungup_impl() const override { return m_writing_count == 0; }
|
virtual bool has_hungup_impl() const override { return m_writing_count == 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -58,6 +59,7 @@ namespace Kernel
|
||||||
size_t m_buffer_tail { 0 };
|
size_t m_buffer_tail { 0 };
|
||||||
|
|
||||||
BAN::Atomic<uint32_t> m_writing_count { 1 };
|
BAN::Atomic<uint32_t> m_writing_count { 1 };
|
||||||
|
BAN::Atomic<uint32_t> m_reading_count { 1 };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <kernel/Thread.h>
|
#include <kernel/Thread.h>
|
||||||
#include <kernel/Timer/Timer.h>
|
#include <kernel/Timer/Timer.h>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
|
@ -26,19 +27,41 @@ namespace Kernel
|
||||||
m_ctime = current_time;
|
m_ctime = current_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pipe::clone_writing()
|
void Pipe::on_clone(int status_flags)
|
||||||
|
{
|
||||||
|
if (status_flags & O_WRONLY)
|
||||||
{
|
{
|
||||||
[[maybe_unused]] auto old_writing_count = m_writing_count.fetch_add(1);
|
[[maybe_unused]] auto old_writing_count = m_writing_count.fetch_add(1);
|
||||||
ASSERT(old_writing_count > 0);
|
ASSERT(old_writing_count > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pipe::close_writing()
|
if (status_flags & O_RDONLY)
|
||||||
|
{
|
||||||
|
[[maybe_unused]] auto old_reading_count = m_reading_count.fetch_add(1);
|
||||||
|
ASSERT(old_reading_count > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pipe::on_close(int status_flags)
|
||||||
|
{
|
||||||
|
if (status_flags & O_WRONLY)
|
||||||
{
|
{
|
||||||
auto old_writing_count = m_writing_count.fetch_sub(1);
|
auto old_writing_count = m_writing_count.fetch_sub(1);
|
||||||
ASSERT(old_writing_count > 0);
|
ASSERT(old_writing_count > 0);
|
||||||
if (old_writing_count != 1)
|
if (old_writing_count != 1)
|
||||||
return;
|
return;
|
||||||
epoll_notify(EPOLLHUP);
|
epoll_notify(EPOLLHUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status_flags & O_RDONLY)
|
||||||
|
{
|
||||||
|
auto old_reading_count = m_reading_count.fetch_sub(1);
|
||||||
|
ASSERT(old_reading_count > 0);
|
||||||
|
if (old_reading_count != 1)
|
||||||
|
return;
|
||||||
|
epoll_notify(EPOLLERR);
|
||||||
|
}
|
||||||
|
|
||||||
m_thread_blocker.unblock();
|
m_thread_blocker.unblock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +107,11 @@ namespace Kernel
|
||||||
|
|
||||||
while (m_buffer_size >= m_buffer.size())
|
while (m_buffer_size >= m_buffer.size())
|
||||||
{
|
{
|
||||||
|
if (m_reading_count == 0)
|
||||||
|
{
|
||||||
|
Thread::current().add_signal(SIGPIPE);
|
||||||
|
return BAN::Error::from_errno(EPIPE);
|
||||||
|
}
|
||||||
LockFreeGuard lock_free(m_mutex);
|
LockFreeGuard lock_free(m_mutex);
|
||||||
TRY(Thread::current().block_or_eintr_or_timeout_ms(m_thread_blocker, 100, false));
|
TRY(Thread::current().block_or_eintr_or_timeout_ms(m_thread_blocker, 100, false));
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,12 +43,7 @@ namespace Kernel
|
||||||
auto& open_file = m_open_files[fd];
|
auto& open_file = m_open_files[fd];
|
||||||
open_file.description = other.m_open_files[fd].description;
|
open_file.description = other.m_open_files[fd].description;
|
||||||
open_file.descriptor_flags = other.m_open_files[fd].descriptor_flags;
|
open_file.descriptor_flags = other.m_open_files[fd].descriptor_flags;
|
||||||
|
open_file.inode()->on_clone(open_file.status_flags());
|
||||||
if (open_file.path() == "<pipe wr>"_sv)
|
|
||||||
{
|
|
||||||
ASSERT(open_file.inode()->is_pipe());
|
|
||||||
static_cast<Pipe*>(open_file.inode().ptr())->clone_writing();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -204,14 +199,10 @@ namespace Kernel
|
||||||
|
|
||||||
(void)close(fildes2);
|
(void)close(fildes2);
|
||||||
|
|
||||||
m_open_files[fildes2].description = m_open_files[fildes].description;
|
auto& open_file = m_open_files[fildes2];
|
||||||
m_open_files[fildes2].descriptor_flags = 0;
|
open_file.description = m_open_files[fildes].description;
|
||||||
|
open_file.descriptor_flags = 0;
|
||||||
if (m_open_files[fildes2].path() == "<pipe wr>"_sv)
|
open_file.inode()->on_clone(open_file.status_flags());
|
||||||
{
|
|
||||||
ASSERT(m_open_files[fildes2].inode()->is_pipe());
|
|
||||||
static_cast<Pipe*>(m_open_files[fildes2].inode().ptr())->clone_writing();
|
|
||||||
}
|
|
||||||
|
|
||||||
return fildes;
|
return fildes;
|
||||||
}
|
}
|
||||||
|
@ -229,13 +220,10 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
const int new_fd = TRY(get_free_fd());
|
const int new_fd = TRY(get_free_fd());
|
||||||
|
|
||||||
m_open_files[new_fd].description = m_open_files[fd].description;
|
auto& open_file = m_open_files[new_fd];
|
||||||
m_open_files[new_fd].descriptor_flags = (cmd == F_DUPFD_CLOEXEC) ? O_CLOEXEC : 0;
|
open_file.description = m_open_files[fd].description;
|
||||||
if (m_open_files[new_fd].path() == "<pipe wr>"_sv)
|
open_file.descriptor_flags = (cmd == F_DUPFD_CLOEXEC) ? O_CLOEXEC : 0;
|
||||||
{
|
open_file.inode()->on_clone(open_file.status_flags());
|
||||||
ASSERT(m_open_files[new_fd].inode()->is_pipe());
|
|
||||||
static_cast<Pipe*>(m_open_files[new_fd].inode().ptr())->clone_writing();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new_fd;
|
return new_fd;
|
||||||
}
|
}
|
||||||
|
@ -313,14 +301,10 @@ namespace Kernel
|
||||||
|
|
||||||
TRY(validate_fd(fd));
|
TRY(validate_fd(fd));
|
||||||
|
|
||||||
if (m_open_files[fd].path() == "<pipe wr>"_sv)
|
auto& open_file = m_open_files[fd];
|
||||||
{
|
open_file.inode()->on_close(open_file.status_flags());
|
||||||
ASSERT(m_open_files[fd].inode()->is_pipe());
|
open_file.description.clear();
|
||||||
static_cast<Pipe*>(m_open_files[fd].inode().ptr())->close_writing();
|
open_file.descriptor_flags = 0;
|
||||||
}
|
|
||||||
|
|
||||||
m_open_files[fd].description.clear();
|
|
||||||
m_open_files[fd].descriptor_flags = 0;
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue