diff options
| author | Stefan Boberg <[email protected]> | 2026-03-23 11:40:11 +0100 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2026-03-23 11:40:11 +0100 |
| commit | a15de3d263a5759ca4f07aa7a2b9e6d494551150 (patch) | |
| tree | 9f1f7abc0fa5e5c09a9d4bedcf0d85f3a32b7246 /src/zenserver-test/zenserver-test.cpp | |
| parent | improve zenserver startup time (#879) (diff) | |
| download | zen-a15de3d263a5759ca4f07aa7a2b9e6d494551150.tar.xz zen-a15de3d263a5759ca4f07aa7a2b9e6d494551150.zip | |
Process management improvements (#881)
This PR improves process lifecycle handling and resilience across several areas:
- **Reclaim stale shared-memory entries instead of exiting** (`zenserver.cpp`): When a zenserver instance fails to attach as a sponsor to an existing process (e.g. because the PID was reused by an unrelated process), the server now clears the stale shared-memory entry and proceeds with normal startup instead of calling `std::exit(1)`.
- **Wait for child process exit in `Kill()` and `Terminate()` on Unix** (`process.cpp`): After sending `SIGTERM` in `Kill()`, the code now waits up to 5s for graceful shutdown (escalating to `SIGKILL` on timeout), matching the Windows behavior. `Terminate()` also waits after `SIGKILL` so the child is properly reaped and doesn't linger as a zombie clogging up the process table.
- **Fix sysctl buffer race in macOS `FindProcess`** (`process.cpp`): The macOS process enumeration now retries the `sysctl` call (up to 3 attempts with 25% buffer padding) to handle the race where the process list changes between the sizing call and the data-fetching call. Also flattens the nesting and fixes the guard/free scoping.
- **Terminate stale processes before integration tests** (`zenserver-test.cpp`, `test.lua`): The integration test runner now accepts a `--kill-stale-processes` flag (passed automatically by `test.lua`) that scans for and terminates any leftover `zenserver`, `zenserver-test`, and `zentest-appstub` processes from previous test runs, logging the executable name and PID of each. This addresses flaky test failures caused by stale processes from prior runs holding ports or other resources.
Diffstat (limited to 'src/zenserver-test/zenserver-test.cpp')
| -rw-r--r-- | src/zenserver-test/zenserver-test.cpp | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/src/zenserver-test/zenserver-test.cpp b/src/zenserver-test/zenserver-test.cpp index fff77957d..cf7ffe4e4 100644 --- a/src/zenserver-test/zenserver-test.cpp +++ b/src/zenserver-test/zenserver-test.cpp @@ -99,7 +99,8 @@ main(int argc, char** argv) // somehow in the future std::string ServerClass; - bool Verbose = false; + bool Verbose = false; + bool KillStale = false; for (int i = 1; i < argc; ++i) { @@ -119,6 +120,44 @@ main(int argc, char** argv) { Verbose = true; } + else if (argv[i] == "--kill-stale-processes"sv) + { + KillStale = true; + } + } + + // Since GHA runners can leave processes behind from a previous test run, we need + // to be able to clean up any stale server processes before starting the tests to + // avoid interference + + if (KillStale) + { + ZEN_INFO("Killing any stale processes from previous test runs..."); + + auto KillStaleProcesses = [](const std::filesystem::path& Executable) { + ZEN_INFO(" Looking for stale '{}' processes...", Executable.filename()); + + for (;;) + { + ProcessHandle StaleProcess; + std::error_code Ec = FindProcess(Executable, StaleProcess, /*IncludeSelf*/ false); + + if (Ec || !StaleProcess.IsValid()) + { + break; + } + + ZEN_WARN("====> Found stale '{}' process (pid {}) from a previous test run - terminating it", + Executable.filename(), + StaleProcess.Pid()); + + StaleProcess.Terminate(0); + } + }; + + KillStaleProcesses(ProgramBaseDir / "zenserver" ZEN_EXE_SUFFIX_LITERAL); + KillStaleProcesses(ProgramBaseDir / "zenserver-test" ZEN_EXE_SUFFIX_LITERAL); + KillStaleProcesses(ProgramBaseDir / "zentest-appstub" ZEN_EXE_SUFFIX_LITERAL); } zen::tests::TestEnv.InitializeForTest(ProgramBaseDir, TestBaseDir, ServerClass); |