2 * Copyright (c) 2007-2009 Dag-Erling Coïdan Smørgrav
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer
10 * in this position and unchanged.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
31 #include <sys/param.h>
33 #include <sys/event.h>
47 * We need a signal handler so kill(2) will interrupt the child
48 * instead of killing it.
51 signal_handler(int sig)
57 * Test that pidfile_open() can create a pidfile and that pidfile_write()
61 test_pidfile_uncontested(void)
63 const char *fn = "test_pidfile_uncontested";
68 pf = pidfile_open(fn, 0600, &other);
69 if (pf == NULL && other != 0)
70 return ("pidfile exists and is locked");
72 return (strerror(errno));
73 if (pidfile_write(pf) != 0) {
76 return ("failed to write PID");
84 * Test that pidfile_open() locks against self.
87 test_pidfile_self(void)
89 const char *fn = "test_pidfile_self";
90 struct pidfh *pf1, *pf2;
95 pf1 = pidfile_open(fn, 0600, &other);
96 if (pf1 == NULL && other != 0)
97 return ("pidfile exists and is locked");
99 return (strerror(errno));
100 if (pidfile_write(pf1) != 0) {
104 return (strerror(serrno));
106 // second open should fail
107 pf2 = pidfile_open(fn, 0600, &other);
112 return ("managed to opened pidfile twice");
114 if (other != getpid()) {
117 return ("pidfile contained wrong PID");
125 * Common code for test_pidfile_{contested,inherited}.
128 common_test_pidfile_child(const char *fn, int parent_open)
130 struct pidfh *pf = NULL;
131 pid_t other = 0, pid = 0;
132 int fd[2], serrno, status;
133 struct kevent event, ke;
139 return (strerror(errno));
142 pf = pidfile_open(fn, 0600, &other);
143 if (pf == NULL && other != 0)
144 return ("pidfile exists and is locked");
146 return (strerror(errno));
151 return (strerror(errno));
155 signal(SIGINT, signal_handler);
157 pf = pidfile_open(fn, 0600, &other);
158 if (pf == NULL && other != 0)
159 return ("pidfile exists and is locked");
161 return (strerror(errno));
163 if (pidfile_write(pf) != 0) {
167 return (strerror(serrno));
171 if (pidfile_write(pf) != 0)
176 EV_SET(&ke, SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
177 /* Attach event to the kqueue. */
178 if (kevent(kq, &ke, 1, NULL, 0, NULL) != 0)
180 /* Inform the parent we are ready to receive SIGINT */
181 if (write(fd[1], "*", 1) != 1)
183 /* Wait for SIGINT received */
184 if (kevent(kq, NULL, 0, &event, 1, NULL) != 1)
193 // wait for the child to signal us
194 if (read(fd[0], &ch, 1) != 1) {
199 return (strerror(errno));
202 // We shouldn't be able to lock the same pidfile as our child
203 pf = pidfile_open(fn, 0600, &other);
207 return ("managed to lock contested pidfile");
210 // Failed to lock, but not because it was contested
213 return (strerror(errno));
216 // Locked by the wrong process
219 return ("pidfile contained wrong PID");
222 // check our child's fate
226 if (kill(pid, SIGINT) != 0)
227 return (strerror(errno));
228 if (waitpid(pid, &status, 0) == -1)
229 return (strerror(errno));
230 if (WIFSIGNALED(status))
231 return ("child caught signal");
232 if (WEXITSTATUS(status) != 0)
233 return ("child returned non-zero status");
240 * Test that pidfile_open() fails when attempting to open a pidfile that
241 * is already locked, and that it returns the correct PID.
244 test_pidfile_contested(void)
246 const char *fn = "test_pidfile_contested";
249 result = common_test_pidfile_child(fn, 0);
254 * Test that the pidfile lock is inherited.
257 test_pidfile_inherited(void)
259 const char *fn = "test_pidfile_inherited";
262 result = common_test_pidfile_child(fn, 1);
268 const char *(*func)(void);
270 { "pidfile_uncontested", test_pidfile_uncontested },
271 { "pidfile_self", test_pidfile_self },
272 { "pidfile_contested", test_pidfile_contested },
273 { "pidfile_inherited", test_pidfile_inherited },
282 nt = sizeof(t) / sizeof(*t);
283 printf("1..%d\n", nt);
284 for (i = 0; i < nt; ++i) {
285 if ((result = t[i].func()) != NULL)
286 printf("not ok %d - %s # %s\n", i + 1,
289 printf("ok %d - %s\n", i + 1,