summaryrefslogtreecommitdiff
path: root/Kernel/Net
diff options
context:
space:
mode:
authorBrian Gianforcaro <bgianf@serenityos.org>2021-08-01 02:34:10 -0700
committerAndreas Kling <kling@serenityos.org>2021-08-03 18:54:23 +0200
commit109c885585a980a68448348873f707b860e5a910 (patch)
treef31c990269c63bb0d1268eff7f5d1f5e21264dae /Kernel/Net
parent8d3b819daf659ee9ce7628d3ddd1e7ca3876fcf5 (diff)
downloadserenity-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.cpp39
-rw-r--r--Kernel/Net/LocalSocket.h6
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;