diff options
author | Brian Gianforcaro <bgianf@serenityos.org> | 2021-08-01 02:34:10 -0700 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-08-03 18:54:23 +0200 |
commit | 109c885585a980a68448348873f707b860e5a910 (patch) | |
tree | f31c990269c63bb0d1268eff7f5d1f5e21264dae /Kernel/Net | |
parent | 8d3b819daf659ee9ce7628d3ddd1e7ca3876fcf5 (diff) | |
download | serenity-109c885585a980a68448348873f707b860e5a910.zip |
Kernel: Handle OOM from DoubleBuffer usage in Net/LocalSocket
LocalSockets keep a DoubleBuffer for both client and server usage.
This change converts the usage from using the default constructor
which is unable to observe OOM, to the new try_create factory and
plumb the result through the constructor.
Diffstat (limited to 'Kernel/Net')
-rw-r--r-- | Kernel/Net/LocalSocket.cpp | 39 | ||||
-rw-r--r-- | Kernel/Net/LocalSocket.h | 6 |
2 files changed, 27 insertions, 18 deletions
diff --git a/Kernel/Net/LocalSocket.cpp b/Kernel/Net/LocalSocket.cpp index 4556952a32..cb698e5059 100644 --- a/Kernel/Net/LocalSocket.cpp +++ b/Kernel/Net/LocalSocket.cpp @@ -33,7 +33,13 @@ void LocalSocket::for_each(Function<void(const LocalSocket&)> callback) KResultOr<NonnullRefPtr<Socket>> LocalSocket::create(int type) { - auto socket = adopt_ref_if_nonnull(new (nothrow) LocalSocket(type)); + auto client_buffer = DoubleBuffer::try_create(); + if (!client_buffer) + return ENOMEM; + auto server_buffer = DoubleBuffer::try_create(); + if (!server_buffer) + return ENOMEM; + auto socket = adopt_ref_if_nonnull(new (nothrow) LocalSocket(type, client_buffer.release_nonnull(), server_buffer.release_nonnull())); if (socket) return socket.release_nonnull(); return ENOMEM; @@ -41,10 +47,11 @@ KResultOr<NonnullRefPtr<Socket>> LocalSocket::create(int type) KResultOr<SocketPair> LocalSocket::create_connected_pair(int type) { - auto socket = adopt_ref_if_nonnull(new (nothrow) LocalSocket(type)); - if (!socket) - return ENOMEM; + auto socket_or_error = LocalSocket::create(type); + if (socket_or_error.is_error()) + return socket_or_error.error(); + auto socket = static_ptr_cast<LocalSocket>(socket_or_error.release_value()); auto description1_result = FileDescription::create(*socket); if (description1_result.is_error()) return description1_result.error(); @@ -66,8 +73,10 @@ KResultOr<SocketPair> LocalSocket::create_connected_pair(int type) return SocketPair { description1_result.release_value(), description2_result.release_value() }; } -LocalSocket::LocalSocket(int type) +LocalSocket::LocalSocket(int type, NonnullOwnPtr<DoubleBuffer> client_buffer, NonnullOwnPtr<DoubleBuffer> server_buffer) : Socket(AF_LOCAL, type, 0) + , m_for_client(move(client_buffer)) + , m_for_server(move(server_buffer)) { { MutexLocker locker(all_sockets().lock()); @@ -79,10 +88,10 @@ LocalSocket::LocalSocket(int type) m_prebind_gid = current_process->egid(); m_prebind_mode = 0666; - m_for_client.set_unblock_callback([this]() { + m_for_client->set_unblock_callback([this]() { evaluate_block_conditions(); }); - m_for_server.set_unblock_callback([this]() { + m_for_server->set_unblock_callback([this]() { evaluate_block_conditions(); }); @@ -260,9 +269,9 @@ bool LocalSocket::can_read(const FileDescription& description, size_t) const if (role == Role::Listener) return can_accept(); if (role == Role::Accepted) - return !has_attached_peer(description) || !m_for_server.is_empty(); + return !has_attached_peer(description) || !m_for_server->is_empty(); if (role == Role::Connected) - return !has_attached_peer(description) || !m_for_client.is_empty(); + return !has_attached_peer(description) || !m_for_client->is_empty(); return false; } @@ -280,9 +289,9 @@ bool LocalSocket::can_write(const FileDescription& description, size_t) const { auto role = this->role(description); if (role == Role::Accepted) - return !has_attached_peer(description) || m_for_client.space_for_writing(); + return !has_attached_peer(description) || m_for_client->space_for_writing(); if (role == Role::Connected) - return !has_attached_peer(description) || m_for_server.space_for_writing(); + return !has_attached_peer(description) || m_for_server->space_for_writing(); return false; } @@ -303,9 +312,9 @@ DoubleBuffer* LocalSocket::receive_buffer_for(FileDescription& description) { auto role = this->role(description); if (role == Role::Accepted) - return &m_for_server; + return m_for_server.ptr(); if (role == Role::Connected) - return &m_for_client; + return m_for_client.ptr(); return nullptr; } @@ -313,9 +322,9 @@ DoubleBuffer* LocalSocket::send_buffer_for(FileDescription& description) { auto role = this->role(description); if (role == Role::Connected) - return &m_for_server; + return m_for_server.ptr(); if (role == Role::Accepted) - return &m_for_client; + return m_for_client.ptr(); return nullptr; } diff --git a/Kernel/Net/LocalSocket.h b/Kernel/Net/LocalSocket.h index 1fc56c59a7..a019e9142b 100644 --- a/Kernel/Net/LocalSocket.h +++ b/Kernel/Net/LocalSocket.h @@ -51,7 +51,7 @@ public: virtual KResult chmod(FileDescription&, mode_t) override; private: - explicit LocalSocket(int type); + explicit LocalSocket(int type, NonnullOwnPtr<DoubleBuffer> client_buffer, NonnullOwnPtr<DoubleBuffer> server_buffer); virtual StringView class_name() const override { return "LocalSocket"; } virtual bool is_local() const override { return true; } bool has_attached_peer(const FileDescription&) const; @@ -93,8 +93,8 @@ private: bool m_accept_side_fd_open { false }; sockaddr_un m_address { 0, { 0 } }; - DoubleBuffer m_for_client; - DoubleBuffer m_for_server; + NonnullOwnPtr<DoubleBuffer> m_for_client; + NonnullOwnPtr<DoubleBuffer> m_for_server; NonnullRefPtrVector<FileDescription> m_fds_for_client; NonnullRefPtrVector<FileDescription> m_fds_for_server; |