Skip to content

Commit 2061c30

Browse files
committed
allow graceful shutdown of dmdserver via SIGTERM, related to #66
1 parent 29573f8 commit 2061c30

File tree

5 files changed

+67
-13
lines changed

5 files changed

+67
-13
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
7575

7676
add_compile_options(-fsanitize=undefined)
7777
add_link_options(-fsanitize=undefined)
78+
79+
add_compile_options(-fno-omit-frame-pointer)
7880
endif()
7981
endif()
8082

platforms/config.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
set -e
44

55
LIBZEDMD_SHA=154772800e8f36378c629f066bfee563862728ac
6-
LIBSERUM_SHA=34e8ad23837b30acaade1e9aaa773d8ea3340622
6+
LIBSERUM_SHA=1f555fa686ba473f4e2d9a05a21f0dc292103032
77
LIBPUPDMD_SHA=124f45e5ddd59ceb339591de88fcca72f8c54612
88

99
if [ -z "${BUILD_TYPE}" ]; then

src/DMD.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,7 +1088,12 @@ void DMD::SerumThread()
10881088
Serum_SetIgnoreUnknownFramesTimeout(Config::GetInstance()->GetIgnoreUnknownFramesTimeout());
10891089
Serum_SetMaximumUnknownFramesToSkip(Config::GetInstance()->GetMaximumUnknownFramesToSkip());
10901090

1091-
if (m_dumpPath[strlen(m_altColorPath) - 1] == '/' || m_dumpPath[strlen(m_altColorPath) - 1] == '\\')
1091+
size_t pathLen = strlen(m_altColorPath);
1092+
if (pathLen == 0)
1093+
{
1094+
snprintf(csvPath, sizeof(csvPath), "./%s.pup.csv", m_romName);
1095+
}
1096+
else if (m_altColorPath[pathLen - 1] == '/' || m_altColorPath[pathLen - 1] == '\\')
10921097
{
10931098
snprintf(csvPath, sizeof(csvPath), "%s%s/%s.pup.csv", m_altColorPath, m_romName, m_romName);
10941099
}
@@ -1859,7 +1864,12 @@ void DMD::DumpDMDTxtThread()
18591864
char suffix[9]; // 8 chars + null terminator
18601865
GenerateRandomSuffix(suffix, 8);
18611866
if (m_dumpPath[0] == '\0') strcpy(m_dumpPath, Config::GetInstance()->GetDumpPath());
1862-
if (m_dumpPath[strlen(m_dumpPath) - 1] == '/' || m_dumpPath[strlen(m_dumpPath) - 1] == '\\')
1867+
size_t pathLen = strlen(m_dumpPath);
1868+
if (pathLen == 0)
1869+
{
1870+
snprintf(filename, sizeof(filename), "./%s-%s.txt", m_dumpPath, name, suffix);
1871+
}
1872+
else if (m_dumpPath[pathLen - 1] == '/' || m_dumpPath[pathLen - 1] == '\\')
18631873
{
18641874
snprintf(filename, sizeof(filename), "%s%s-%s.txt", m_dumpPath, name, suffix);
18651875
}

src/DMDServer.cpp

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ bool DMDServer::Start(const char* addr, in_port_t port)
3737
return false;
3838
}
3939

40+
m_acceptor.set_non_blocking();
41+
4042
m_running.store(true, std::memory_order_release);
4143
m_acceptThread = new std::thread(&DMDServer::AcceptLoop, this);
4244
return true;
@@ -56,25 +58,27 @@ void DMDServer::Stop()
5658
std::unique_lock<std::mutex> lock(m_threadMutex);
5759
m_currentThreadId = 0;
5860
m_disconnectOtherClients = 0;
61+
lock.unlock();
5962
}
6063

6164
void DMDServer::AcceptLoop()
6265
{
6366
uint32_t threadId = 0;
6467

65-
(void)m_running.load(std::memory_order_acquire);
66-
6768
while (m_running.load(std::memory_order_relaxed))
6869
{
6970
sockpp::inet_address peer;
7071
sockpp::tcp_socket sock = m_acceptor.accept(&peer);
7172

7273
if (!sock)
7374
{
74-
if (m_acceptor.last_error() != EWOULDBLOCK)
75+
if (m_acceptor.last_error() == EWOULDBLOCK)
7576
{
76-
Log(DMDUtil_LogLevel_ERROR, "Error accepting connection: %s", m_acceptor.last_error_str().c_str());
77+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
78+
continue;
7779
}
80+
81+
Log(DMDUtil_LogLevel_ERROR, "Error accepting connection: %s", m_acceptor.last_error_str().c_str());
7882
continue;
7983
}
8084

@@ -90,20 +94,38 @@ void DMDServer::AcceptLoop()
9094

9195
void DMDServer::ClientThread(sockpp::tcp_socket sock, uint32_t threadId)
9296
{
97+
// Socket auf non-blocking setzen
98+
sock.set_non_blocking();
99+
93100
uint8_t buffer[sizeof(DMDUtil::DMD::Update)];
94101
DMDUtil::DMD::StreamHeader* pStreamHeader = (DMDUtil::DMD::StreamHeader*)malloc(sizeof(DMDUtil::DMD::StreamHeader));
95102
ssize_t n;
96-
// Disconnect others is only allowed once per client.
97103
bool handleDisconnectOthers = true;
98104
bool logged = false;
99105

100106
DMDUtil::Log(DMDUtil_LogLevel_INFO, "%d: New DMD client %d connected", threadId, threadId);
101107

102-
while (threadId == m_currentThreadId || m_disconnectOtherClients == 0 || m_disconnectOtherClients <= threadId)
108+
while (m_running.load(std::memory_order_relaxed) &&
109+
(threadId == m_currentThreadId || m_disconnectOtherClients == 0 || m_disconnectOtherClients <= threadId))
103110
{
104111
n = sock.read_n(buffer, sizeof(DMDUtil::DMD::StreamHeader));
105-
// If the client disconnects or if a network error ocurres, exit the loop and terminate this thread.
106-
if (n <= 0) break;
112+
113+
if (n < 0)
114+
{
115+
if (sock.last_error() == EWOULDBLOCK)
116+
{
117+
std::this_thread::sleep_for(std::chrono::milliseconds(1));
118+
continue;
119+
}
120+
121+
// network error or connection closed
122+
break;
123+
}
124+
else if (n == 0)
125+
{
126+
// connection closed by client
127+
break;
128+
}
107129

108130
if (n == sizeof(DMDUtil::DMD::StreamHeader))
109131
{

src/server.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#include <signal.h>
2+
13
#include "DMDUtil/DMDUtil.h"
24
#include "Logger.h"
35
#include "cargs.h"
@@ -7,6 +9,7 @@ using namespace std;
79
bool opt_verbose = false;
810
bool opt_fixedAltColorPath = false;
911
bool opt_fixedPupPath = false;
12+
static volatile bool running = true;
1013

1114
static struct cag_option options[] = {
1215
{.identifier = 'c',
@@ -59,13 +62,28 @@ void DMDUTILCALLBACK LogCallback(DMDUtil_LogLevel logLevel, const char* format,
5962
fprintf(stderr, "%s\n", buffer);
6063
}
6164

65+
// Signal Handler für graceful shutdown
66+
void SignalHandler(int signum)
67+
{
68+
if (signum == SIGTERM)
69+
{
70+
DMDUtil::Log(DMDUtil_LogLevel_INFO, "Received SIGTERM, shutting down...");
71+
running = false;
72+
}
73+
}
74+
6275
int main(int argc, char* argv[])
6376
{
77+
// Signal Handler registrieren
78+
signal(SIGTERM, SignalHandler);
79+
6480
DMDUtil::Config* pConfig = DMDUtil::Config::GetInstance();
6581
pConfig->SetDMDServer(false); // This is the server. It must not connect to a different server!
6682

6783
cag_option_context cag_context;
6884
bool opt_wait = false;
85+
bool opt_fixedAltColorPath = false;
86+
bool opt_fixedPupPath = false;
6987

7088
cag_option_init(&cag_context, options, CAG_ARRAY_SIZE(options), argc, argv);
7189
while (cag_option_fetch(&cag_context))
@@ -79,10 +97,12 @@ int main(int argc, char* argv[])
7997
else if (identifier == 'o')
8098
{
8199
pConfig->SetAltColorPath(cag_option_get_value(&cag_context));
100+
opt_fixedAltColorPath = true;
82101
}
83102
else if (identifier == 'u')
84103
{
85104
pConfig->SetPUPVideosPath(cag_option_get_value(&cag_context));
105+
opt_fixedPupPath = true;
86106
}
87107
else if (identifier == 'a')
88108
{
@@ -141,14 +161,14 @@ int main(int argc, char* argv[])
141161
opt_fixedAltColorPath = true;
142162
}
143163

144-
DMDUtil::DMDServer server(pDmd);
164+
DMDUtil::DMDServer server(pDmd, opt_fixedAltColorPath, opt_fixedPupPath);
145165

146166
if (!server.Start(pConfig->GetDMDServerAddr(), pConfig->GetDMDServerPort()))
147167
{
148168
return 1;
149169
}
150170

151-
while (server.IsRunning() && pDmd->HasDisplay())
171+
while (running && server.IsRunning() && pDmd->HasDisplay())
152172
{
153173
std::this_thread::sleep_for(std::chrono::milliseconds(100));
154174
}

0 commit comments

Comments
 (0)