This source file includes following definitions.
- pcmk__pid_active
- pcmk__read_pidfile
- pcmk__pidfile_matches
- pcmk__lock_pidfile
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <sys/stat.h>
15
16 #include <crm/crm.h>
17
18 int
19 pcmk__pid_active(pid_t pid, const char *daemon)
20 {
21 static pid_t last_asked_pid = 0;
22 int rc = 0;
23
24 if (pid <= 0) {
25 return EINVAL;
26 }
27
28 rc = kill(pid, 0);
29 if ((rc < 0) && (errno == ESRCH)) {
30 return ESRCH;
31
32 } else if ((daemon == NULL) || !pcmk__procfs_has_pids()) {
33
34
35 if (rc == 0) {
36 return pcmk_rc_ok;
37 }
38 rc = errno;
39 if (last_asked_pid != pid) {
40 crm_info("Cannot examine PID %lld: %s",
41 (long long) pid, pcmk_rc_str(rc));
42 last_asked_pid = pid;
43 }
44 return rc;
45
46 } else {
47
48
49 bool checked_through_kill = (rc == 0);
50 char exe_path[PATH_MAX], myexe_path[PATH_MAX];
51
52 rc = pcmk__procfs_pid2path(pid, exe_path, sizeof(exe_path));
53 if (rc != pcmk_rc_ok) {
54 if (rc != EACCES) {
55
56 if ((kill(pid, 0) < 0) && (errno == ESRCH)) {
57 return ESRCH;
58 }
59 }
60 if (last_asked_pid != pid) {
61 if (rc == EACCES) {
62 crm_info("Could not get executable for PID %lld: %s "
63 QB_XS " rc=%d",
64 (long long) pid, pcmk_rc_str(rc), rc);
65 } else {
66 crm_err("Could not get executable for PID %lld: %s "
67 QB_XS " rc=%d",
68 (long long) pid, pcmk_rc_str(rc), rc);
69 }
70 last_asked_pid = pid;
71 }
72 if (rc == EACCES) {
73
74 return checked_through_kill? pcmk_rc_ok : EACCES;
75 } else {
76 return ESRCH;
77 }
78 }
79
80 if (daemon[0] != '/') {
81 rc = snprintf(myexe_path, sizeof(myexe_path), CRM_DAEMON_DIR"/%s",
82 daemon);
83 } else {
84 rc = snprintf(myexe_path, sizeof(myexe_path), "%s", daemon);
85 }
86
87 if (rc > 0 && rc < sizeof(myexe_path) && !strcmp(exe_path, myexe_path)) {
88 return pcmk_rc_ok;
89 }
90 }
91
92 return ESRCH;
93 }
94
95 #define LOCKSTRLEN 11
96
97
98
99
100
101
102
103
104
105
106 int
107 pcmk__read_pidfile(const char *filename, pid_t *pid)
108 {
109 int fd;
110 struct stat sbuf;
111 int rc = pcmk_rc_ok;
112 long long pid_read = 0;
113 char buf[LOCKSTRLEN + 1];
114
115 CRM_CHECK((filename != NULL) && (pid != NULL), return EINVAL);
116
117 fd = open(filename, O_RDONLY);
118 if (fd < 0) {
119 return errno;
120 }
121
122 if ((fstat(fd, &sbuf) >= 0) && (sbuf.st_size < LOCKSTRLEN)) {
123 sleep(2);
124
125
126 }
127
128 if (read(fd, buf, sizeof(buf)) < 1) {
129 rc = errno;
130 goto bail;
131 }
132
133 errno = 0;
134 rc = sscanf(buf, "%lld", &pid_read);
135
136 if (rc > 0) {
137 if (pid_read <= 0) {
138 rc = ESRCH;
139 } else {
140 rc = pcmk_rc_ok;
141 *pid = (pid_t) pid_read;
142 crm_trace("Read pid %lld from %s", pid_read, filename);
143 }
144 } else if (rc == 0) {
145 rc = ENODATA;
146 } else {
147 rc = errno;
148 }
149
150 bail:
151 close(fd);
152 return rc;
153 }
154
155
156
157
158
159
160
161
162
163
164
165
166
167 int
168 pcmk__pidfile_matches(const char *filename, pid_t expected_pid,
169 const char *expected_name, pid_t *pid)
170 {
171 pid_t pidfile_pid = 0;
172 int rc = pcmk__read_pidfile(filename, &pidfile_pid);
173
174 if (pid) {
175 *pid = pidfile_pid;
176 }
177
178 if (rc != pcmk_rc_ok) {
179
180 unlink(filename);
181 rc = ENOENT;
182
183 } else if ((expected_pid > 0) && (pidfile_pid == expected_pid)) {
184
185 rc = pcmk_rc_ok;
186
187 } else if (pcmk__pid_active(pidfile_pid, expected_name) == ESRCH) {
188
189 unlink(filename);
190 rc = ENOENT;
191
192 } else if ((expected_pid > 0) && (pidfile_pid != expected_pid)) {
193
194 rc = EEXIST;
195 }
196
197 return rc;
198 }
199
200
201
202
203
204
205
206
207
208
209 int
210 pcmk__lock_pidfile(const char *filename, const char *name)
211 {
212 pid_t mypid = getpid();
213 int fd = 0;
214 int rc = 0;
215 char buf[LOCKSTRLEN + 2];
216
217 rc = pcmk__pidfile_matches(filename, 0, name, NULL);
218 if ((rc != pcmk_rc_ok) && (rc != ENOENT)) {
219
220 return rc;
221 }
222
223 fd = open(filename, O_CREAT | O_WRONLY | O_EXCL, 0644);
224 if (fd < 0) {
225 return errno;
226 }
227
228 snprintf(buf, sizeof(buf), "%*lld\n", LOCKSTRLEN - 1, (long long) mypid);
229 rc = write(fd, buf, LOCKSTRLEN);
230 close(fd);
231
232 if (rc != LOCKSTRLEN) {
233 crm_perror(LOG_ERR, "Incomplete write to %s", filename);
234 return errno;
235 }
236
237 rc = pcmk__pidfile_matches(filename, mypid, name, NULL);
238 if (rc != pcmk_rc_ok) {
239
240 unlink(filename);
241 }
242 return rc;
243 }