~siborgium/prelockdpp

846bf17f62f658082021956c5f3be267d2c55509 — Sergey Smirnykh 2 years ago fd38b14
Use dirent & co to enumerate /proc entries
1 files changed, 56 insertions(+), 13 deletions(-)

M main.cpp
M main.cpp => main.cpp +56 -13
@@ 8,11 8,12 @@

#include <cstring>

#include <dirent.h>
#include <sys/epoll.h>
#include <sys/mman.h>
#include <sys/signalfd.h>
#include <sys/timerfd.h>

#include <sys/types.h>
#include <signal.h>
#include <unistd.h>



@@ 42,10 43,16 @@ struct errno_exception: public std::runtime_error {
        // intentionally left blank
    }
};
struct file_not_found_error: public std::runtime_error {
    using std::runtime_error::runtime_error;
};
struct process_lookup_error: public std::runtime_error {
    using std::runtime_error::runtime_error;
};

struct config {
    fs::path dump_path{ "/var/lib/prelockdpp/dump.json" };
    time_t   interval_sec{ 300 };
    time_t   interval_sec{ 5 };
};

struct sc_info {


@@ 110,6 117,8 @@ struct context {
    sc_info                               info;
    config&                               cfg;

    std::vector<int>                      pids;

    context(config& cfg): cfg{ cfg } {
        start_time = std::chrono::steady_clock::now();
        self_pid = getpid();


@@ 134,19 143,52 @@ struct context {
            throw std::runtime_error{ concat("mlockall failed ", errno_) };
        }
    }
    auto get_pid_list() {
        std::vector<int> pids;
        for (auto&& entry: fs::directory_iterator{ "/proc" }) {
            auto&& name = entry.path().filename().native();
            auto& new_pid = pids.emplace_back();
            auto [_, ec ] = std::from_chars(name.data(), name.data() + name.size(), new_pid);
            switch (unsigned(ec != std::errc()) + unsigned(new_pid == self_pid) * 2) {
                case 0: break;
                case 1: /* do nothing */ break;
                case 2: pids.pop_back(); break;
                case 3: throw std::logic_error{ "Unreachable" };
    auto const& get_pid_list() {
        pids.clear();

        DIR* dir = opendir("/proc");
        if (!dir) {
            throw errno_exception("opendir(/proc) failed", errno);
        }
        errno = 0;
        auto* pid = &pids.emplace_back(self_pid);
        while (dirent* entry = readdir(dir)) {
            auto end = entry->d_name + strlen(entry->d_name);
            auto [_, ec] = std::from_chars(entry->d_name, end, *pid);
            if (ec == std::errc() && _ == end && *pid != self_pid) {
                pid = &pids.emplace_back(self_pid);
            }
        }
        if (*pid == self_pid) {
            pids.pop_back();
        }
        if (errno) {
            throw errno_exception("readdir(proc) failed", errno);
        }
        closedir(dir);
        return pids;
    }
    auto get_uniq_id(int pid) {
        try {
            throw std::runtime_error{ "Unimplemented" };
        } catch (const file_not_found_error&) {
            return -1;
        } catch (const process_lookup_error&) {
            return -1;
        }
    }
    auto get_current_set() {
        timespec m0, p0;
        if (clock_gettime(CLOCK_MONOTONIC, &m0)) {
            throw errno_exception("clock_gettime(MONOTONIC) failed", errno);
        }
        if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &p0)) {
            throw errno_exception("clock_gettime(PROCESS_CPUTIME) failed", errno);
        }
        for (auto&& pid: get_pid_list()) {
            std::cout << pid << '\n';
        }

    }
};



@@ 185,6 227,7 @@ struct lock_context {
            throw std::logic_error{ "Reading from timer fd returned fewer bytes than expected" };
        }
        std::cerr << "Timer ticked!\n";
        ctx.get_current_set();
    }
    void on_signal() {
        signalfd_siginfo info;