migrate all manual closing to new UniqueFd

Makes things cleaner.
This commit is contained in:
Lily Tsuru 2024-02-03 19:19:10 -05:00
parent dcda1bfd1c
commit bc8ed5eb8a
7 changed files with 71 additions and 19 deletions

View File

@ -13,12 +13,8 @@ namespace nanosm {
}
}
EventLoop::~EventLoop() {
if(epollFd == -1) {
close(epollFd);
}
}
EventLoop::~EventLoop() = default;
void EventLoop::Post(PostFn func) {
if(!func)
return;

View File

@ -62,13 +62,14 @@ namespace nanosm {
void Stop();
private:
int epollFd {};
nanosm::UniqueFd epollFd {};
bool shouldStop { false };
/// All tracked IO objects.
std::set<std::shared_ptr<IoObject>> ioObjects {};
/// FIFO queue of functions to run semi-asynchronously
/// One function is ran every eventloop tick.
std::deque<PostFn> postCallbacks {};
};

View File

@ -36,7 +36,7 @@ namespace nanosm {
void Process::Respawn() {
pid = Clone3({
.flags = CLONE_PIDFD,
.pidfd = std::bit_cast<u64>(&pidFd),
.pidfd = std::bit_cast<u64>(pidFd.GetFDMutPtr()),
.exit_signal = SIGCHLD,
});
@ -95,10 +95,8 @@ namespace nanosm {
}
void Process::Reset() {
if(pidFd != -1) {
close(pidFd);
pidFd = -1;
}
if(pidFd.Valid())
pidFd.Reset();
pid = -1;
siginfo = {};

View File

@ -4,6 +4,7 @@
#include <sys/wait.h>
#include "EventLoop.hpp"
#include "Types.hpp"
namespace nanosm {
@ -36,7 +37,7 @@ namespace nanosm {
private:
void Reset();
int pidFd { -1 };
nanosm::UniqueFd pidFd { -1 };
pid_t pid { -1 };
siginfo_t siginfo {};
std::string commLine;

View File

@ -12,13 +12,11 @@ namespace nanosm {
}
}
Timer::~Timer() {
Reset();
}
Timer::~Timer() = default;
void Timer::Reset() {
if(timerFd != -1)
close(timerFd);
if(timerFd.Valid())
timerFd.Reset();
}
int Timer::GetFD() const {

View File

@ -1,5 +1,6 @@
#pragma once
#include "EventLoop.hpp"
#include "Types.hpp"
namespace nanosm {
@ -23,7 +24,7 @@ namespace nanosm {
void Arm(u32 durationSeconds);
private:
int timerFd { -1 };
nanosm::UniqueFd timerFd { -1 };
std::function<void()> cb;
};

View File

@ -46,4 +46,61 @@ namespace nanosm {
usize size {};
};
/// A "smart pointer" for file descriptors.
struct UniqueFd {
constexpr UniqueFd()
: UniqueFd(-1) {}
constexpr explicit UniqueFd(int fd)
: fd(fd) {
}
constexpr UniqueFd(UniqueFd&& from) {
fd = std::move(from.fd);
from.fd = -1;
}
constexpr ~UniqueFd() {
Reset();
}
/// Assigns a new file descriptor to this UniqueFd,
/// closing the old one.
constexpr UniqueFd& operator=(int fd) {
Reset(fd);
return *this;
}
constexpr int GetFD() const { return fd; }
/// Gets a mutable pointer to the file descriptor value.
///
/// You should only use this in clone3() or such system
/// calls that expect an address to a value to populate
/// with a known-valid/good file descriptor. Otherwise,
/// this function is very unsafe and a easy way to FD leak.
int* GetFDMutPtr() { return &fd; }
constexpr operator int() const {
return GetFD();
}
constexpr bool Valid() const {
return fd != -1;
}
constexpr void Reset(int newFd = -1) {
// If a previously valid file descriptor was assigned,
// then we have to close it to avoid leaking file
// descriptors. Do so here.
if(Valid())
close(fd);
fd = newFd;
}
private:
int fd { -1 };
};
} // namespace nanosm