Implement RAII wrapper over file descriptors

The `FileDescriptor` class is a RAII wrapper over FDs which handles their lifetimes alongside other C++ semantics such as moving and copying. It has been used in `skyline::kernel::MemoryManager` to handle the lifetime of the ashmem FD correctly, it wasn't being destroyed earlier which can result in leaking FDs across runs.
This commit is contained in:
PixelyIon 2022-04-02 22:14:31 +05:30
parent 7ce2a903a1
commit 344c5f2a62
2 changed files with 72 additions and 2 deletions

View File

@ -0,0 +1,69 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
#pragma once
#include <unistd.h>
#include "base.h"
namespace skyline {
/**
* @brief A RAII wrapper around Linux file descriptors which automatically closes the file descriptor when it goes out of scope and duplicates them on copies
* @note This class should **always** be moved rather than copied where possible to avoid a system call for duplicating file descriptors
*/
class FileDescriptor {
private:
int fd;
public:
FileDescriptor() : fd(-1) {}
FileDescriptor(int fd) : fd(fd) {}
FileDescriptor &operator=(int newFd) {
if (fd != -1)
close(fd);
fd = newFd;
return *this;
}
FileDescriptor(const FileDescriptor &other) : fd(dup(other.fd)) {
if (fd == -1)
throw exception("Failed to duplicate file descriptor: {}", strerror(errno));
}
FileDescriptor &operator=(const FileDescriptor &other) {
if (fd != -1)
close(fd);
fd = dup(other.fd);
if (fd == -1)
throw exception("Failed to duplicate file descriptor: {}", strerror(errno));
return *this;
}
FileDescriptor(FileDescriptor &&other) : fd(other.fd) {
other.fd = -1;
}
FileDescriptor &operator=(FileDescriptor &&other) {
if (fd != -1)
close(fd);
fd = other.fd;
other.fd = -1;
return *this;
}
~FileDescriptor() {
if (fd != -1)
close(fd);
}
operator int() const {
return fd;
}
int operator*() const {
return fd;
}
};
}

View File

@ -3,8 +3,9 @@
#pragma once #pragma once
#include <common.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <common.h>
#include <common/file_descriptor.h>
namespace skyline { namespace skyline {
namespace memory { namespace memory {
@ -226,7 +227,7 @@ namespace skyline {
memory::Region stack{}; memory::Region stack{};
memory::Region tlsIo{}; //!< TLS/IO memory::Region tlsIo{}; //!< TLS/IO
int memoryFd{}; //!< The file descriptor of the memory backing for the entire guest address space FileDescriptor memoryFd{}; //!< The file descriptor of the memory backing for the entire guest address space
std::shared_mutex mutex; //!< Synchronizes any operations done on the VMM, it's locked in shared mode by readers and exclusive mode by writers std::shared_mutex mutex; //!< Synchronizes any operations done on the VMM, it's locked in shared mode by readers and exclusive mode by writers