summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2023-01-13 15:52:17 +0100
committerRoland Reichwein <mail@reichwein.it>2023-01-13 15:52:17 +0100
commit02fbb7a8ea54d1188b2a8410ecd64ae93ac0210e (patch)
tree8eb309e7db647f6edaadac21d8d63d98d36cf6bb
parente29ca1929f3aae5288c03be40e67061e245a90ea (diff)
Added process functions
-rw-r--r--common.mk2
-rw-r--r--debian/changelog1
-rw-r--r--debian/control2
-rw-r--r--process.cpp112
-rw-r--r--process.h9
5 files changed, 124 insertions, 2 deletions
diff --git a/common.mk b/common.mk
index 405982d..563602e 100644
--- a/common.mk
+++ b/common.mk
@@ -101,4 +101,4 @@ LIBS+= \
-lstdc++fs
endif
-LIBS+=-lboost_context -lboost_system -lpthread
+LIBS+=-lboost_context -lboost_system -lpthread -lfmt
diff --git a/debian/changelog b/debian/changelog
index 9c72966..0bba3c2 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,6 +1,7 @@
libreichwein (1.2) UNRELEASED; urgency=medium
* Added process.h+cpp: Reichwein::Process::is_running()
+ * process.h+cpp: Added functions for checking running pids
-- Roland Reichwein <mail@reichwein.it> Sat, 07 Jan 2023 19:15:07 +0100
diff --git a/debian/control b/debian/control
index 83988c8..3b883b5 100644
--- a/debian/control
+++ b/debian/control
@@ -2,7 +2,7 @@ Source: libreichwein
Section: devel
Priority: optional
Maintainer: Roland Reichwein <mail@reichwein.it>
-Build-Depends: debhelper (>= 12), libboost-all-dev | libboost1.71-all-dev, clang | g++-9, llvm | g++-9, lld | g++-9, googletest, gcovr
+Build-Depends: debhelper (>= 12), libboost-all-dev | libboost1.71-all-dev, clang | g++-9, llvm | g++-9, lld | g++-9, googletest, gcovr, libfmt-dev
Standards-Version: 4.5.0
Homepage: http://www.reichwein.it/libreichwein/
diff --git a/process.cpp b/process.cpp
index b30ef3d..67cf1ce 100644
--- a/process.cpp
+++ b/process.cpp
@@ -1,9 +1,16 @@
#include "process.h"
#include <filesystem>
+#include <fstream>
#include <string>
+#include <thread>
+
+#include <boost/algorithm/string.hpp>
+
+#include <fmt/core.h>
#include "file.h"
+#include "stringhelper.h"
namespace fs = std::filesystem;
@@ -25,3 +32,108 @@ bool Reichwein::Process::is_running(pid_t pid)
return state == "R" || state == "S";
}
+
+// tcp: tcp or tcp6
+bool Reichwein::Process::tcp_is_pid_listening_on(const std::string& tcp, pid_t pid, int port)
+{
+ std::string filename{fmt::format("/proc/{}/net/{}", pid, tcp)};
+ std::ifstream f{filename, std::ios::in};
+ // e.g.:
+ // sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
+ // 0: 00000000:C799 00000000:0000 0A 00000000:00000000 00:00000000 00000000 107 0 21869 1 00000000335416a4 100 0 0 10 0
+ std::string s;
+ std::getline(f, s); // skip head line
+ while (std::getline(f, s)) {
+ boost::algorithm::trim_left(s);
+
+ size_t pos_space1{s.find(' ')};
+ if (pos_space1 == std::string::npos)
+ throw std::runtime_error("Expected first space in " + filename);
+
+ size_t pos_colon1{s.find(':', pos_space1 + 1)};
+ if (pos_colon1 == std::string::npos)
+ throw std::runtime_error("Expected first colon in " + filename);
+
+ size_t pos_space2{s.find(' ', pos_colon1 + 1)};
+ if (pos_space2 == std::string::npos)
+ throw std::runtime_error("Expected second space in " + filename);
+
+ std::string port_s{s.substr(pos_colon1 + 1, pos_space2 - (pos_colon1 + 1))};
+ auto current_port{std::stoul(port_s, nullptr, 16)};
+ if (current_port != port)
+ continue;
+
+ // now, we are in a line related to matching local port
+
+ size_t pos_space3{s.find(' ', pos_space2 + 1)};
+ if (pos_space3 == std::string::npos)
+ throw std::runtime_error("Expected third space in " + filename);
+
+ size_t pos_space4{s.find(' ', pos_space3 + 1)};
+ if (pos_space4 == std::string::npos)
+ throw std::runtime_error("Expected fourth space in " + filename);
+
+ std::string state_s{s.substr(pos_space3 + 1, pos_space4 - (pos_space3 + 1))};
+ if (state_s == "0A") // listening state TCP_LISTEN, from <linux_source>/include/net/tcp_states.h
+ return true;
+ }
+
+ return false; // not found
+}
+
+bool Reichwein::Process::is_pid_listening_on(pid_t pid, int port)
+{
+ return tcp_is_pid_listening_on("tcp", pid, port) || tcp_is_pid_listening_on("tcp6", pid, port);
+}
+
+bool Reichwein::Process::unix_is_pid_listening_on(pid_t pid, const std::string& path)
+{
+ std::string filename{fmt::format("/proc/{}/net/unix", pid)};
+ std::ifstream f{filename, std::ios::in};
+ // e.g.:
+ // Num RefCount Protocol Flags Type St Inode Path
+ // 000000009ce259a6: 00000003 00000000 00000000 0001 03 29015
+ // 000000003a686108: 00000003 00000000 00000000 0001 03 27263 /run/user/1000/pulse/native
+ // 000000006d62b584: 00000002 00000000 00010000 0001 01 6126359 @/tmp/dbus-b8l6vAYN
+ std::string s;
+ std::getline(f, s); // skip head line
+ while (std::getline(f, s)) {
+ boost::algorithm::trim_left(s);
+ std::vector<std::string> columns{Reichwein::Stringhelper::split(s, " ")};
+ if (columns.size() < 8)
+ continue;
+
+ std::string current_path = columns[7];
+
+ if (current_path[0] == '@')
+ current_path = current_path.substr(1);
+
+ if (current_path != path)
+ continue;
+
+ std::string state = columns[5];
+
+ // I would expect "0A" here, since net/unix/af_unix.c also uses
+ // TCP_LISTEN etc. as in TCP sockets /proc/{}/net/tcp.
+ // But practically, I always get "01"
+ if (state == "0A" || state == "01") // listening state TCP_LISTEN, from <linux_source>/include/net/tcp_states.h
+ return true;
+ }
+
+ return false; // not found
+}
+
+void Reichwein::Process::wait_for_pid_listening_on(pid_t pid, int port)
+{
+ while (!is_pid_listening_on(pid, port)) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
+}
+
+void Reichwein::Process::wait_for_pid_listening_on(pid_t pid, const std::string& path)
+{
+ while (!unix_is_pid_listening_on(pid, path)) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
+}
+
diff --git a/process.h b/process.h
index b13a54c..fb24017 100644
--- a/process.h
+++ b/process.h
@@ -1,5 +1,7 @@
#pragma once
+#include <string>
+
#include <sys/types.h>
#define EXPORT __attribute__((visibility("default")))
@@ -8,4 +10,11 @@ namespace Reichwein::Process {
EXPORT bool is_running(pid_t pid);
+EXPORT bool unix_is_pid_listening_on(pid_t pid, const std::string& path);
+EXPORT void wait_for_pid_listening_on(pid_t pid, const std::string& path);
+
+EXPORT bool tcp_is_pid_listening_on(const std::string& tcp, pid_t pid, int port);
+EXPORT bool is_pid_listening_on(pid_t pid, int port);
+EXPORT void wait_for_pid_listening_on(pid_t pid, int port);
+
} // namespace