Kea 3.1.3
pid_file.cc
Go to the documentation of this file.
1// Copyright (C) 2015-2025 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <util/pid_file.h>
10
11#include <cerrno>
12#include <cstring>
13
14#include <fcntl.h>
15#include <signal.h>
16#include <sys/file.h>
17#include <unistd.h>
18
19namespace isc {
20namespace util {
21
22int
24 std::ifstream fs(filename_.c_str());
25 int pid;
26 bool good;
27
28 // If we weren't able to open the file treat
29 // it as if the process wasn't running
30 if (!fs.is_open()) {
31 return (0);
32 }
33
34 // Try to get the pid, get the status and get rid of the file
35 fs >> pid;
36 good = fs.good();
37 fs.close();
38
39 // If we weren't able to read a pid send back an exception
40 if (!good) {
41 isc_throw(PIDCantReadPID, "Unable to read PID from file '"
42 << filename_ << "'");
43 }
44
45 // If the process is still running return its pid.
46 if (kill(pid, 0) == 0) {
47 return (pid);
48 }
49
50 // No process
51 return (0);
52}
53
54void
56 write(getpid());
57}
58
59void
60PIDFile::write(int pid) const {
61 std::ofstream fs(filename_.c_str(), std::ofstream::trunc);
62
63 if (!fs.is_open()) {
64 isc_throw(PIDFileError, "Unable to open PID file '"
65 << filename_ << "' for write");
66 }
67
68 // File is open, write the pid.
69 fs << pid << std::endl;
70
71 bool good = fs.good();
72 fs.close();
73
74 if (!good) {
75 isc_throw(PIDFileError, "Unable to write to PID file '"
76 << filename_ << "'");
77 }
78}
79
80void
82 if ((remove(filename_.c_str()) != 0) &&
83 (errno != ENOENT)) {
84 isc_throw(PIDFileError, "Unable to delete PID file '"
85 << filename_ << "'");
86 }
87}
88
89 PIDLock::PIDLock(const std::string& lockname, bool blocking)
90 : lockname_(lockname), fd_(-1), locked_(false) {
91 // Open the lock file.
92 fd_ = open(lockname_.c_str(), O_RDONLY | O_CREAT, 0600);
93 if (fd_ == -1) {
94 if ((errno == ENOENT) && !blocking) {
95 // Ignoring missing component in the path.
96 locked_ = true;
97 return;
98 }
99 std::string errmsg = strerror(errno);
100 isc_throw(PIDFileError, "cannot create pid lockfile '"
101 << lockname_ << "': " << errmsg);
102 }
103 // Try to acquire the lock. If we can't somebody else is actively
104 // using it.
105 int ret = flock(fd_, LOCK_EX | (blocking ? 0 : LOCK_NB));
106 if (ret == 0) {
107 locked_ = true;
108 return;
109 }
110 if (errno != EWOULDBLOCK) {
111 std::string errmsg = strerror(errno);
112 isc_throw(PIDFileError, "cannot lock pid lockfile '"
113 << lockname_ << "': " << errmsg);
114 }
115}
116
118 if (fd_ != -1) {
119 if (locked_) {
120 // For symmetry as the close releases the lock...
121 static_cast<void>(flock(fd_, LOCK_UN));
122 }
123 static_cast<void>(close(fd_));
124 static_cast<void>(remove(lockname_.c_str()));
125 }
126 fd_ = -1;
127 locked_ = false;
128}
129
130} // namespace isc::util
131} // namespace isc
Exception thrown when an error occurs trying to read a PID from an opened file.
Definition pid_file.h:28
Exception thrown when an error occurs during PID file processing.
Definition pid_file.h:20
void write() const
Get PID of the current process and write it to the file.
Definition pid_file.cc:55
void deleteFile() const
Delete the PID file.
Definition pid_file.cc:81
int check() const
Read the PID in from the file and check it.
Definition pid_file.cc:23
~PIDLock()
Destructor.
Definition pid_file.cc:117
PIDLock(const std::string &lockname, bool blocking=false)
Constructor.
Definition pid_file.cc:89
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Defines the logger used by the top-level component of kea-lfc.