diff --git a/Kernel/FileSystem/FIFO.cpp b/Kernel/FileSystem/FIFO.cpp index 74c4de39f3..871cb031d1 100644 --- a/Kernel/FileSystem/FIFO.cpp +++ b/Kernel/FileSystem/FIFO.cpp @@ -24,9 +24,12 @@ static Lockable>& all_fifos() static int s_next_fifo_id = 1; -NonnullRefPtr FIFO::create(uid_t uid) +RefPtr FIFO::try_create(uid_t uid) { - return adopt_ref(*new FIFO(uid)); + auto buffer = DoubleBuffer::try_create(); + if (buffer) + return adopt_ref_if_nonnull(new (nothrow) FIFO(uid, buffer.release_nonnull())); + return {}; } KResultOr> FIFO::open_direction(FIFO::Direction direction) @@ -70,15 +73,16 @@ KResultOr> FIFO::open_direction_blocking(FIFO::Di return description; } -FIFO::FIFO(uid_t uid) - : m_uid(uid) +FIFO::FIFO(uid_t uid, NonnullOwnPtr buffer) + : m_buffer(move(buffer)) + , m_uid(uid) { MutexLocker locker(all_fifos().lock()); all_fifos().resource().set(this); m_fifo_id = ++s_next_fifo_id; // Use the same block condition for read and write - m_buffer.set_unblock_callback([this]() { + m_buffer->set_unblock_callback([this]() { evaluate_block_conditions(); }); } @@ -115,19 +119,19 @@ void FIFO::detach(Direction direction) bool FIFO::can_read(const FileDescription&, size_t) const { - return !m_buffer.is_empty() || !m_writers; + return !m_buffer->is_empty() || !m_writers; } bool FIFO::can_write(const FileDescription&, size_t) const { - return m_buffer.space_for_writing() || !m_readers; + return m_buffer->space_for_writing() || !m_readers; } KResultOr FIFO::read(FileDescription&, u64, UserOrKernelBuffer& buffer, size_t size) { - if (!m_writers && m_buffer.is_empty()) + if (!m_writers && m_buffer->is_empty()) return 0; - return m_buffer.read(buffer, size); + return m_buffer->read(buffer, size); } KResultOr FIFO::write(FileDescription&, u64, const UserOrKernelBuffer& buffer, size_t size) @@ -137,7 +141,7 @@ KResultOr FIFO::write(FileDescription&, u64, const UserOrKernelBuffer& b return EPIPE; } - return m_buffer.write(buffer, size); + return m_buffer->write(buffer, size); } String FIFO::absolute_path(const FileDescription&) const diff --git a/Kernel/FileSystem/FIFO.h b/Kernel/FileSystem/FIFO.h index 39ef6b8042..e9c62ce232 100644 --- a/Kernel/FileSystem/FIFO.h +++ b/Kernel/FileSystem/FIFO.h @@ -24,7 +24,7 @@ public: Writer }; - static NonnullRefPtr create(uid_t); + static RefPtr try_create(uid_t); virtual ~FIFO() override; uid_t uid() const { return m_uid; } @@ -49,11 +49,11 @@ private: virtual StringView class_name() const override { return "FIFO"; } virtual bool is_fifo() const override { return true; } - explicit FIFO(uid_t); + explicit FIFO(uid_t, NonnullOwnPtr buffer); unsigned m_writers { 0 }; unsigned m_readers { 0 }; - DoubleBuffer m_buffer; + NonnullOwnPtr m_buffer; uid_t m_uid { 0 }; diff --git a/Kernel/FileSystem/Inode.cpp b/Kernel/FileSystem/Inode.cpp index d8e31de11c..abf4b1128a 100644 --- a/Kernel/FileSystem/Inode.cpp +++ b/Kernel/FileSystem/Inode.cpp @@ -185,8 +185,11 @@ NonnullRefPtr Inode::fifo() VERIFY(metadata().is_fifo()); // FIXME: Release m_fifo when it is closed by all readers and writers - if (!m_fifo) - m_fifo = FIFO::create(metadata().uid); + if (!m_fifo) { + m_fifo = FIFO::try_create(metadata().uid); + // FIXME: We need to be able to observe OOM here. + VERIFY(!m_fifo.is_null()); + } VERIFY(m_fifo); return *m_fifo; diff --git a/Kernel/Syscalls/pipe.cpp b/Kernel/Syscalls/pipe.cpp index 3dd0c72b52..dfced6b1c3 100644 --- a/Kernel/Syscalls/pipe.cpp +++ b/Kernel/Syscalls/pipe.cpp @@ -20,7 +20,9 @@ KResultOr Process::sys$pipe(int pipefd[2], int flags) return EINVAL; u32 fd_flags = (flags & O_CLOEXEC) ? FD_CLOEXEC : 0; - auto fifo = FIFO::create(uid()); + auto fifo = FIFO::try_create(uid()); + if (!fifo) + return ENOMEM; auto open_reader_result = fifo->open_direction(FIFO::Direction::Reader); if (open_reader_result.is_error())