aboutsummaryrefslogtreecommitdiff
path: root/src/zenserver
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2026-03-21 21:43:22 +0100
committerGitHub Enterprise <[email protected]>2026-03-21 21:43:22 +0100
commit14ca5b35d0fc477ba30f10b80f937b523fd7e930 (patch)
tree8aab2acfec8be1af4bf0dffdb4badc3b64bf8385 /src/zenserver
parentfix null stats provider crash when build store is not configured (#875) (diff)
downloadzen-14ca5b35d0fc477ba30f10b80f937b523fd7e930.tar.xz
zen-14ca5b35d0fc477ba30f10b80f937b523fd7e930.zip
Interprocess pipe support (for stdout/stderr capture) (#866)
- **RAII pipe handles for child process stdout/stderr capture**: `StdoutPipeHandles` is now a proper RAII type with automatic cleanup, move semantics, and partial close support. This makes it safe to use pipes for capturing child process output without risking handle/fd leaks. - **Optional separate stderr pipe**: `CreateProcOptions` now accepts a `StderrPipe` field so callers can capture stdout and stderr independently. When null (default), stderr shares the stdout pipe as before. - **LogStreamListener with pluggable handler**: The TCP log stream listener accepts connections from remote processes and delivers parsed log lines through a `LogStreamHandler` interface, set dynamically via `SetHandler()`. This allows any client to receive log messages without depending on a specific console implementation. - **TcpLogStreamSink for zen::logging**: A logging sink that forwards log messages to a `LogStreamListener` over TCP, using the native `zen::logging::Sink` infrastructure with proper thread-safe synchronization. - **Reliable child process exit codes on Linux**: `waitpid` result handling is fixed so `ProcessHandle::GetExitCode()` returns the real exit code. `ProcessHandle::Reset()` reaps zombies directly, replacing the global `IgnoreChildSignals()` which prevented exit code collection entirely. Also fixes a TOCTOU race in `ProcessHandle::Wait()` on Linux/Mac. - **Pipe capture test suite**: Tests covering stdout/stderr capture via pipes (both shared and separate modes), RAII cleanup, move semantics, and exit code propagation using `zentest-appstub` as the child process. - **Service command integration tests**: Shell-based integration tests for `zen service` covering the full lifecycle (install, status, start, stop, uninstall) on all three platforms — Linux (systemd), macOS (launchd), and Windows (SCM via PowerShell). - **Test script reorganization**: Platform-specific test scripts moved from `scripts/test_scripts/` into `scripts/test_linux/`, `test_mac/`, and `test_windows/`.
Diffstat (limited to 'src/zenserver')
-rw-r--r--src/zenserver/diag/logging.cpp23
-rw-r--r--src/zenserver/main.cpp4
2 files changed, 23 insertions, 4 deletions
diff --git a/src/zenserver/diag/logging.cpp b/src/zenserver/diag/logging.cpp
index 178c3d3b5..38b15480a 100644
--- a/src/zenserver/diag/logging.cpp
+++ b/src/zenserver/diag/logging.cpp
@@ -13,6 +13,7 @@
#include <zencore/string.h>
#include <zenutil/logging.h>
#include <zenutil/logging/rotatingfilesink.h>
+#include <zenutil/splitconsole/tcplogstreamsink.h>
#include "otlphttp.h"
@@ -28,6 +29,7 @@ InitializeServerLogging(const ZenServerConfig& InOptions, bool WithCacheService)
.IsTest = InOptions.IsTest,
.NoConsoleOutput = InOptions.LoggingConfig.NoConsoleOutput,
.QuietConsole = InOptions.LoggingConfig.QuietConsole,
+ .ForceColor = InOptions.LoggingConfig.ForceColor,
.AbsLogFile = InOptions.LoggingConfig.AbsLogFile,
.LogId = InOptions.LoggingConfig.LogId};
@@ -81,6 +83,27 @@ InitializeServerLogging(const ZenServerConfig& InOptions, bool WithCacheService)
}
#endif
+ if (!InOptions.LoggingConfig.LogStreamEndpoint.empty())
+ {
+ std::string Endpoint = InOptions.LoggingConfig.LogStreamEndpoint;
+ std::string Host = "localhost";
+ uint16_t Port = 0;
+
+ auto ColonPos = Endpoint.rfind(':');
+ if (ColonPos != std::string::npos)
+ {
+ Host = Endpoint.substr(0, ColonPos);
+ std::optional<uint16_t> P = ParseInt<uint16_t>(std::string_view(Endpoint).substr(ColonPos + 1));
+ Port = P.value_or(0);
+ }
+
+ if (Port > 0)
+ {
+ logging::SinkPtr StreamSink(new TcpLogStreamSink(Host, Port, "zenserver"));
+ zen::logging::Default()->AddSink(std::move(StreamSink));
+ }
+ }
+
FinishInitializeLogging(LogOptions);
const zen::Oid ServerSessionId = zen::GetSessionId();
diff --git a/src/zenserver/main.cpp b/src/zenserver/main.cpp
index bf328c499..dff162b1c 100644
--- a/src/zenserver/main.cpp
+++ b/src/zenserver/main.cpp
@@ -123,10 +123,6 @@ AppMain(int argc, char* argv[])
signal(SIGINT, utils::SignalCallbackHandler);
signal(SIGTERM, utils::SignalCallbackHandler);
-#if ZEN_PLATFORM_LINUX
- IgnoreChildSignals();
-#endif
-
try
{
typename Main::Config ServerOptions;