aboutsummaryrefslogtreecommitdiff
path: root/src/zenutil/zenserverprocess.cpp
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2024-04-18 12:44:26 +0200
committerGitHub Enterprise <[email protected]>2024-04-18 12:44:26 +0200
commit6d634ab59c05adf1ba028d95b16031a7f8e8db2a (patch)
tree87e8215fed65506f98f6838b2af08c4ffd5819f0 /src/zenutil/zenserverprocess.cpp
parentzen startup hardening (#49) (diff)
downloadzen-6d634ab59c05adf1ba028d95b16031a7f8e8db2a.tar.xz
zen-6d634ab59c05adf1ba028d95b16031a7f8e8db2a.zip
improved lock file handling (#50)
- Feature: `zen down` - --`data-dir` to specify a data directory to deduce which zen instance to bring down - Feature: `zen attach` - --`data-dir` to specify a data directory to deduce which zen instance to attach to222 - Feature: `zen status` - --`port` filter running zen instances based on port - --`data-dir` filter running zen instances based on information in the data directory - Improvement: Trying to load a compact binary object from an empty file no longer causes access violation
Diffstat (limited to 'src/zenutil/zenserverprocess.cpp')
-rw-r--r--src/zenutil/zenserverprocess.cpp113
1 files changed, 103 insertions, 10 deletions
diff --git a/src/zenutil/zenserverprocess.cpp b/src/zenutil/zenserverprocess.cpp
index 384371df3..9a2ec9774 100644
--- a/src/zenutil/zenserverprocess.cpp
+++ b/src/zenutil/zenserverprocess.cpp
@@ -2,6 +2,8 @@
#include "zenutil/zenserverprocess.h"
+#include <zencore/compactbinary.h>
+#include <zencore/compactbinarybuilder.h>
#include <zencore/except.h>
#include <zencore/filesystem.h>
#include <zencore/fmtutils.h>
@@ -237,7 +239,7 @@ ZenServerState::InitializeReadOnly()
}
ZenServerState::ZenServerEntry*
-ZenServerState::Lookup(int DesiredListenPort)
+ZenServerState::Lookup(int DesiredListenPort) const
{
for (int i = 0; i < m_MaxEntryCount; ++i)
{
@@ -258,6 +260,27 @@ ZenServerState::Lookup(int DesiredListenPort)
}
ZenServerState::ZenServerEntry*
+ZenServerState::LookupByEffectivePort(int Port) const
+{
+ for (int i = 0; i < m_MaxEntryCount; ++i)
+ {
+ uint16_t EntryPort = m_Data[i].EffectiveListenPort;
+ if (EntryPort != 0)
+ {
+ if (EntryPort == Port)
+ {
+ if (IsProcessRunning(m_Data[i].Pid))
+ {
+ return &m_Data[i];
+ }
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+ZenServerState::ZenServerEntry*
ZenServerState::Register(int DesiredListenPort)
{
if (m_Data == nullptr)
@@ -324,7 +347,7 @@ ZenServerState::Sweep()
}
void
-ZenServerState::Snapshot(std::function<void(const ZenServerEntry&)>&& Callback)
+ZenServerState::Snapshot(std::function<void(const ZenServerEntry&)>&& Callback) const
{
if (m_Data == nullptr)
{
@@ -333,11 +356,14 @@ ZenServerState::Snapshot(std::function<void(const ZenServerEntry&)>&& Callback)
for (int i = 0; i < m_MaxEntryCount; ++i)
{
- ZenServerEntry& Entry = m_Data[i];
+ const ZenServerEntry& Entry = m_Data[i];
- if (Entry.DesiredListenPort)
+ if (Entry.Pid != 0 && Entry.DesiredListenPort)
{
- Callback(Entry);
+ if (IsProcessRunning(Entry.Pid.load()))
+ {
+ Callback(Entry);
+ }
}
}
}
@@ -696,11 +722,8 @@ ZenServerInstance::AttachToRunningServer(int BasePort)
else
{
State.Snapshot([&](const ZenServerState::ZenServerEntry& InEntry) {
- if (IsProcessRunning(InEntry.Pid.load()))
- {
- ZEN_INFO("Found entry pid {}, baseport {}", InEntry.Pid.load(), InEntry.DesiredListenPort.load());
- Entry = &InEntry;
- }
+ ZEN_INFO("Found entry pid {}, baseport {}", InEntry.Pid.load(), InEntry.DesiredListenPort.load());
+ Entry = &InEntry;
});
}
@@ -850,4 +873,74 @@ ZenServerInstance::Terminate()
return true;
}
+CbObject
+MakeLockFilePayload(const LockFileInfo& Info)
+{
+ CbObjectWriter Cbo;
+ Cbo << "pid" << Info.Pid << "data" << PathToUtf8(Info.DataDir) << "port" << Info.EffectiveListenPort << "session_id" << Info.SessionId
+ << "ready" << Info.Ready << "executable" << PathToUtf8(Info.ExecutablePath);
+ return Cbo.Save();
+}
+LockFileInfo
+ReadLockFilePayload(const CbObject& Payload)
+{
+ LockFileInfo Info;
+ Info.Pid = Payload["pid"].AsInt32();
+ Info.SessionId = Payload["session_id"].AsObjectId();
+ Info.EffectiveListenPort = Payload["port"].AsUInt16();
+ Info.Ready = Payload["ready"].AsBool();
+ Info.DataDir = Payload["data"].AsU8String();
+ Info.ExecutablePath = Payload["executable"].AsU8String();
+ return Info;
+}
+
+bool
+ValidateLockFileInfo(const LockFileInfo& Info, std::string& OutReason)
+{
+ if (Info.Pid == 0)
+ {
+ OutReason = fmt::format("process ({}) is invalid", Info.Pid);
+ return false;
+ }
+ if (!IsProcessRunning(Info.Pid))
+ {
+ OutReason = fmt::format("process ({}) is not running", Info.Pid);
+ return false;
+ }
+ if (Info.SessionId == Oid::Zero)
+ {
+ OutReason = fmt::format("session id ({}) is not valid", Info.SessionId);
+ return false;
+ }
+ if (Info.EffectiveListenPort == 0)
+ {
+ OutReason = fmt::format("listen port ({}) is not valid", Info.EffectiveListenPort);
+ return false;
+ }
+ if (!std::filesystem::is_directory(Info.DataDir))
+ {
+ OutReason = fmt::format("data directory ('{}') does not exist", Info.DataDir);
+ return false;
+ }
+ if (!Info.ExecutablePath.empty())
+ {
+ std::error_code Ec;
+ std::filesystem::path PidPath = GetProcessExecutablePath(Info.Pid, Ec);
+ if (Ec)
+ {
+ OutReason = fmt::format("failed to find executable path of process ('{}'), {}", Info.Pid, Ec.message());
+ return false;
+ }
+ if (PidPath != Info.ExecutablePath)
+ {
+ OutReason = fmt::format("executable path of process ({}: '{}') does not match executable path '{}'",
+ Info.Pid,
+ PidPath,
+ Info.ExecutablePath);
+ return false;
+ }
+ }
+ return true;
+}
+
} // namespace zen