mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 21:57:35 +00:00
LibIPC: Close received IPC::File fd's by default unless taken
When receiving a file descriptor over IPC, the receiver must now call take_fd() on the IPC::File to take over the descriptor. Otherwise, IPC::File will close the file on destruction.
This commit is contained in:
parent
384d047e3e
commit
7f2d8e8884
5 changed files with 50 additions and 5 deletions
|
@ -78,7 +78,7 @@ static DefaultDocumentClient s_default_document_client;
|
|||
void ClientConnection::handle(const Messages::LanguageServer::FileOpened& message)
|
||||
{
|
||||
auto file = Core::File::construct(this);
|
||||
if (!file->open(message.file().fd(), Core::IODevice::ReadOnly, Core::File::ShouldCloseFileDescriptor::Yes)) {
|
||||
if (!file->open(message.file().take_fd(), Core::IODevice::ReadOnly, Core::File::ShouldCloseFileDescriptor::Yes)) {
|
||||
errno = file->error();
|
||||
perror("open");
|
||||
dbgln("Failed to open project file");
|
||||
|
|
|
@ -78,7 +78,7 @@ static DefaultDocumentClient s_default_document_client;
|
|||
void ClientConnection::handle(const Messages::LanguageServer::FileOpened& message)
|
||||
{
|
||||
auto file = Core::File::construct(this);
|
||||
if (!file->open(message.file().fd(), Core::IODevice::ReadOnly, Core::File::ShouldCloseFileDescriptor::Yes)) {
|
||||
if (!file->open(message.file().take_fd(), Core::IODevice::ReadOnly, Core::File::ShouldCloseFileDescriptor::Yes)) {
|
||||
errno = file->error();
|
||||
perror("open");
|
||||
dbgln("Failed to open project file");
|
||||
|
|
|
@ -174,7 +174,7 @@ bool Decoder::decode([[maybe_unused]] File& file)
|
|||
dbgln("recvfd: {}", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
file = File(fd);
|
||||
file = File(fd, File::ConstructWithReceivedFileDescriptor);
|
||||
return true;
|
||||
#else
|
||||
[[maybe_unused]] auto fd = m_sockfd;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Sergey Bugaev <bugaevc@serenityos.org>
|
||||
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -26,9 +27,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Noncopyable.h>
|
||||
#include <AK/StdLibExtras.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace IPC {
|
||||
|
||||
class File {
|
||||
AK_MAKE_NONCOPYABLE(File);
|
||||
|
||||
public:
|
||||
// Must have a default constructor, because LibIPC
|
||||
// default-constructs arguments prior to decoding them.
|
||||
|
@ -40,10 +47,48 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
// Tagged constructor for fd's that should be closed on destruction unless take_fd() is called.
|
||||
enum Tag {
|
||||
ConstructWithReceivedFileDescriptor = 1,
|
||||
};
|
||||
File(int fd, Tag)
|
||||
: m_fd(fd)
|
||||
, m_close_on_destruction(true)
|
||||
{
|
||||
}
|
||||
|
||||
File(File&& other)
|
||||
: m_fd(exchange(other.m_fd, -1))
|
||||
, m_close_on_destruction(exchange(other.m_close_on_destruction, false))
|
||||
{
|
||||
}
|
||||
|
||||
File& operator=(File&& other)
|
||||
{
|
||||
if (this != &other) {
|
||||
m_fd = exchange(other.m_fd, -1);
|
||||
m_close_on_destruction = exchange(other.m_close_on_destruction, false);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~File()
|
||||
{
|
||||
if (m_close_on_destruction && m_fd != -1)
|
||||
close(m_fd);
|
||||
}
|
||||
|
||||
int fd() const { return m_fd; }
|
||||
|
||||
// NOTE: This is 'const' since generated IPC messages expose all parameters by const reference.
|
||||
[[nodiscard]] int take_fd() const
|
||||
{
|
||||
return exchange(m_fd, -1);
|
||||
}
|
||||
|
||||
private:
|
||||
int m_fd { -1 };
|
||||
mutable int m_fd { -1 };
|
||||
bool m_close_on_destruction { false };
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ RefPtr<Download> Client::start_download(const String& method, const String& url,
|
|||
auto download_id = response->download_id();
|
||||
if (download_id < 0 || !response->response_fd().has_value())
|
||||
return nullptr;
|
||||
auto response_fd = response->response_fd().value().fd();
|
||||
auto response_fd = response->response_fd().value().take_fd();
|
||||
auto download = Download::create_from_id({}, *this, download_id);
|
||||
download->set_download_fd({}, response_fd);
|
||||
m_downloads.set(download_id, download);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue