This is an automated email from the ASF dual-hosted git repository.
git-hulk pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/kvrocks.git
The following commit(s) were added to refs/heads/unstable by this push:
new 7cf8e6422 fix(server): add O_TRUNC when creating PID file to avoid
stale content (#3598)
7cf8e6422 is described below
commit 7cf8e642274ad47a606859f4e3d940ffa1532c76
Author: weimeng <[email protected]>
AuthorDate: Thu Sep 3 12:32:34 2026 +0800
fix(server): add O_TRUNC when creating PID file to avoid stale content
(#3598)
What problem does this change solve?
CreatePidFile opens the PID file with O_RDWR | O_CREAT but without
O_TRUNC. If a stale PID file already exists from a previous run and the
old PID string is longer than the new one, open() + write() will only
overwrite the first N bytes of the file, leaving the trailing bytes from
the old content intact. This results in a corrupted PID file.
Example:
Step File content Note
Previous run (PID=12345) 12345 correct
New run (PID=678), without O_TRUNC 67845 corrupted — trailing 45 is
stale
New run (PID=678), with O_TRUNC 678 correct
A corrupted PID file can cause process management tools (e.g., kill
$(cat pidfile), systemd, init scripts) to target the wrong process or
fail to stop/restart the service.
How does this change fix the problem?
Add O_TRUNC to the open() flags in CreatePidFile so the file is
truncated to zero length before writing the new PID, ensuring no stale
bytes remain.
Changes
- src/cli/pid_util.h: Add O_TRUNC flag to the open() call in
CreatePidFile.
- tests/cppunit/pid_util_test.cc: Add unit tests covering:
- - Truncation on existing file: Write a longer fake PID first, then
call CreatePidFile and verify the content matches exactly the current
PID with no leftover bytes.
- - Creation from scratch: Verify CreatePidFile works correctly when no
file exists.
- - RemovePidFile: Verify the PID file is properly removed.
---------
Co-authored-by: weimeng <[email protected]>
Co-authored-by: Twice <[email protected]>
Co-authored-by: hulk <[email protected]>
---
src/cli/pid_util.h | 2 +-
tests/cppunit/pid_util_test.cc | 60 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/src/cli/pid_util.h b/src/cli/pid_util.h
index eb7c41b2c..bbf73c492 100644
--- a/src/cli/pid_util.h
+++ b/src/cli/pid_util.h
@@ -27,7 +27,7 @@
#include "unique_fd.h"
inline Status CreatePidFile(const std::string &path) {
- auto fd = UniqueFD(open(path.data(), O_RDWR | O_CREAT, 0660));
+ auto fd = UniqueFD(open(path.data(), O_RDWR | O_CREAT | O_TRUNC, 0660));
if (!fd) {
return Status::FromErrno();
}
diff --git a/tests/cppunit/pid_util_test.cc b/tests/cppunit/pid_util_test.cc
new file mode 100644
index 000000000..56681b2ae
--- /dev/null
+++ b/tests/cppunit/pid_util_test.cc
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "cli/pid_util.h"
+
+#include <fcntl.h>
+#include <gtest/gtest.h>
+#include <unistd.h>
+
+#include <cstdio>
+#include <fstream>
+#include <string>
+
+TEST(PidUtil, CreatePidFileTruncatesExistingContent) {
+ // Simulate a stale PID file whose content is longer than the current PID.
+ // Without O_TRUNC, CreatePidFile would overwrite only the first N bytes,
+ // leaving trailing characters from the old content and producing an
+ // incorrect PID string (e.g. old "12345678" + new "999" => "99945678").
+ const std::string path = "/tmp/kvrocks_pid_util_test.pid";
+
+ // Write a fake old PID that is guaranteed to be longer than any real PID.
+ {
+ auto fd = UniqueFD(open(path.data(), O_RDWR | O_CREAT | O_TRUNC, 0660));
+ ASSERT_TRUE(fd);
+ const std::string old_pid = "99999999"; // 8 chars
+ ASSERT_TRUE(util::Write(*fd, old_pid).IsOK());
+ }
+
+ // Now call CreatePidFile which should overwrite with the real (shorter) PID.
+ auto status = CreatePidFile(path);
+ ASSERT_TRUE(status.IsOK());
+
+ // Read back and verify the content is exactly the current PID.
+ std::ifstream ifs(path);
+ std::string content((std::istreambuf_iterator<char>(ifs)),
std::istreambuf_iterator<char>());
+ ifs.close();
+
+ std::string expected = std::to_string(getpid());
+ EXPECT_EQ(content, expected);
+ EXPECT_EQ(content.size(), expected.size()) << "PID file should not contain
leftover bytes from previous content";
+
+ RemovePidFile(path);
+}